Пример #1
0
        static private Boolean FilterCallback(IntPtr sendDataPtr, IntPtr replyDataPtr)
        {
            bool retVal = true;

            try
            {
                FilterAPI.MessageSendData messageSend = new FilterAPI.MessageSendData();
                messageSend = (FilterAPI.MessageSendData)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.MessageSendData));

                if (FilterAPI.MESSAGE_SEND_VERIFICATION_NUMBER != messageSend.VerificationNumber)
                {
                    EventManager.WriteMessage(139, "FilterCallback", EventLevel.Error, "Received message corrupted.Please check if the MessageSendData structure is correct.");
                    return(false);
                }

                if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_ENCRYPTION_IV_AND_KEY)
                {
                    if ((replyDataPtr.ToInt64() != 0))
                    {
                        //this is the customized tag data which was attahced to the encrypted file when it was created.
                        uint   tagDataLength = messageSend.DataBufferLength;
                        byte[] tagData       = messageSend.DataBuffer;

                        FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));
                        messageReply.MessageId   = messageSend.MessageId;
                        messageReply.MessageType = messageSend.MessageType;

                        //get permission for secure shared file from server, here just demo the server in local,
                        //in reality, your server could be in remote computer.
                        retVal = DRServer.GetFileAccessPermission(ref messageSend, ref messageReply);

                        if (retVal)
                        {
                            messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                        }
                        else
                        {
                            //if you don't want to authorize the process to read the encrytped file,you can set the value as below:
                            messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                            messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        }

                        Marshal.StructureToPtr(messageReply, replyDataPtr, true);

                        if (!retVal)
                        {
                            messageSend.Status = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterCallback", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }

            return(retVal);
        }
Пример #2
0
        public static Boolean FilterCallback(IntPtr sendDataPtr, IntPtr replyDataPtr)
        {
            Boolean ret = true;

            try
            {
                FilterAPI.MessageSendData messageSend = new FilterAPI.MessageSendData();
                messageSend = (FilterAPI.MessageSendData)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.MessageSendData));

                if (FilterAPI.MESSAGE_SEND_VERIFICATION_NUMBER != messageSend.VerificationNumber)
                {
                    EventManager.WriteMessage(139, "FilterCallback", EventLevel.Error, "Received message corrupted.Please check if the MessageSendData structure is correct.");
                    return(false);
                }

                MessageInfo.DisplayFilterMessage(messageSend);

                if (replyDataPtr.ToInt64() != 0)
                {
                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));

                    //here you can control the IO behaviour and modify the data.
                    FilterService.IOAccessControl(messageSend, ref messageReply);

                    messageReply.MessageId    = messageSend.MessageId;
                    messageReply.MessageType  = messageSend.MessageType;
                    messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;


                    //to comple the PRE_IO
                    //messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                    //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;

                    Marshal.StructureToPtr(messageReply, replyDataPtr, true);
                }


                return(ret);
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterCallback", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }
        }
Пример #3
0
        Boolean FilterCallback(IntPtr sendDataPtr, IntPtr replyDataPtr)
        {
            Boolean ret = true;

            try
            {
                FilterAPI.MessageSendData messageSend = (FilterAPI.MessageSendData)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.MessageSendData));

                if (FilterAPI.MESSAGE_SEND_VERIFICATION_NUMBER != messageSend.VerificationNumber)
                {
                    MessageBoxHelper.PrepToCenterMessageBoxOnForm(this);
                    MessageBox.Show("Received message corrupted.Please check if the MessageSendData structure is correct.");

                    EventManager.WriteMessage(139, "FilterCallback", EventLevel.Error, "Received message corrupted.Please check if the MessageSendData structure is correct.");
                    return(false);
                }

                filterMessage.AddMessage(messageSend);

                if (replyDataPtr.ToInt64() != 0)
                {
                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));

                    if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_REG_CALLBACK_INFO)
                    {
                        //this is registry callback request
                        RegistryHandler.AuthorizeRegistryAccess(messageSend, ref messageReply);
                        Marshal.StructureToPtr(messageReply, replyDataPtr, true);
                    }
                }

                return(ret);
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterCallback", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }
        }
Пример #4
0
        public static bool IOAccessControl(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            bool ret = true;

            try
            {
                messageReply.MessageId   = messageSend.MessageId;
                messageReply.MessageType = messageSend.MessageType;

                //
                //here you can control all the registered IO requests,block the access or modify the I/O data base on the file IO information from MessageSend struture
                //
                //

                //if you don't want to change anything to this IO request, just let it pass through as below setting:
                //messageReply.FilterStatus = 0;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                //if you want to block the access this IO request before it goes down to the file system, you can return the status as below,
                //it is only for pre IO requests, it means the user IO reuqests will be completed here instead of going down to the file system.
                //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;

                //if you want to modify the IO data and complete the pre IO with your own data, you can return status as below:
                // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                // messageReply.DataBufferLength = the return data buffer length.
                // messageReply.DataBuffer = the data you want to return.
                // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                FilterAPI.MessageType       messageType = (FilterAPI.MessageType)messageSend.MessageType;
                WinData.FileInfomationClass infoClass   = (WinData.FileInfomationClass)messageSend.InfoClass;

                uint   dataLength = messageSend.DataBufferLength;
                byte[] data       = messageSend.DataBuffer;

                //here is some IO information for your reference:
                if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FO_REMOTE_ORIGIN) > 0)
                {
                    //this is file access request comes from remote network server
                }

                //you can check the file create option with this data:
                //"DesiredAccess: messageSend.DesiredAccess
                //"Disposition:" + ((WinData.Disposition)messageSend.Disposition).ToString();
                //"ShareAccess:" + ((WinData.ShareAccess)messageSend.SharedAccess).ToString();
                //"CreateOptions:"messageSend.CreateOptions


                //Here is the demo to copy file content before it was deleted.-----------------------------------------------
                bool isFileDeleted = false;
                if (messageSend.Status == (uint)NtStatus.Status.Success)
                {
                    if (messageType == FilterAPI.MessageType.POST_CREATE)
                    {
                        if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FILE_DELETE_ON_CLOSE) > 0)
                        {
                            isFileDeleted = true;
                        }
                    }
                    else if (messageType == FilterAPI.MessageType.POST_SET_INFORMATION)
                    {
                        if (infoClass == WinData.FileInfomationClass.FileDispositionInformation)
                        {
                            isFileDeleted = true;
                        }
                    }

                    if (isFileDeleted)
                    {
                        IntPtr fileHandle = IntPtr.Zero;
                        bool   retVal     = FilterAPI.GetFileHandleInFilter(messageSend.FileName, (uint)FileAccess.Read, ref fileHandle);
                        if (retVal)
                        {
                            SafeFileHandle sHandle    = new SafeFileHandle(fileHandle, true);
                            FileStream     fileStream = new FileStream(sHandle, FileAccess.Read);

                            //copy your data here...

                            fileStream.Close();
                        }
                    }
                }
                //End -----------------------------------------------



                switch (messageType)
                {
                case FilterAPI.MessageType.PRE_CREATE:
                {
                    //here you reparse the file open to another new file name

                    //string newReparseFileName = "\\??\\c:\\myNewFile.txt";
                    //byte[] returnData = Encoding.Unicode.GetBytes(newReparseFileName);
                    //Array.Copy(returnData, messageReply.DataBuffer, returnData.Length);
                    //messageReply.DataBufferLength = (uint)returnData.Length;
                    //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                    //messageReply.ReturnStatus = (uint)NtStatus.Status.Reparse;

                    break;
                }


                case FilterAPI.MessageType.PRE_CACHE_READ:
                case FilterAPI.MessageType.POST_CACHE_READ:
                case FilterAPI.MessageType.PRE_NOCACHE_READ:
                case FilterAPI.MessageType.POST_NOCACHE_READ:
                case FilterAPI.MessageType.PRE_PAGING_IO_READ:
                case FilterAPI.MessageType.POST_PAGING_IO_READ:
                case FilterAPI.MessageType.PRE_CACHE_WRITE:
                case FilterAPI.MessageType.POST_CACHE_WRITE:
                case FilterAPI.MessageType.PRE_NOCACHE_WRITE:
                case FilterAPI.MessageType.POST_NOCACHE_WRITE:
                case FilterAPI.MessageType.PRE_PAGING_IO_WRITE:
                case FilterAPI.MessageType.POST_PAGING_IO_WRITE:
                {
                    //byte[] returnData = //new data you want to modify the read/write data;
                    //Array.Copy(returnData, messageReply.DataBuffer, returnData.Length);
                    //messageReply.DataBufferLength = (uint)returnData.Length;

                    ////for pre IO,use this one
                    //// messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;

                    // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                    // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;


                    break;
                }

                case FilterAPI.MessageType.PRE_SET_INFORMATION:
                case FilterAPI.MessageType.POST_SET_INFORMATION:
                case FilterAPI.MessageType.PRE_QUERY_INFORMATION:
                case FilterAPI.MessageType.POST_QUERY_INFORMATION:
                {
                    ret = true;
                    switch (infoClass)
                    {
                    case WinData.FileInfomationClass.FileRenameInformation:
                    {
                        //you can block file rename as below
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                        break;
                    }

                    case WinData.FileInfomationClass.FileDispositionInformation:
                    {
                        //you can block file delete as below
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                        break;
                    }

                    case WinData.FileInfomationClass.FileEndOfFileInformation:
                    {
                        //change file size
                        break;
                    }

                    case WinData.FileInfomationClass.FileBasicInformation:
                    {
                        //file basic information
                        break;
                    }

                    case WinData.FileInfomationClass.FileStandardInformation:
                    {
                        //file standard information
                        break;
                    }

                    case WinData.FileInfomationClass.FileNetworkOpenInformation:
                    {
                        //file network information
                        break;
                    }

                    case WinData.FileInfomationClass.FileInternalInformation:
                    {
                        //file internal inofrmation
                        break;
                    }

                    default:
                    {
                        ret = false;
                        break;
                    }
                    }

                    break;
                }
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(174, "IOAccessControl", EventLevel.Error, "IOAccessControl failed." + ex.Message);
            }

            return(ret);
        }
Пример #5
0
        Boolean FilterCallback(IntPtr sendDataPtr, IntPtr replyDataPtr)
        {
            Boolean ret = true;

            try
            {
                //for file access right unit test, to handle the monitor or control IO callback, reference the FileMonitor/FileProtector project
                FilterAPI.MessageSendData messageSend = (FilterAPI.MessageSendData)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.MessageSendData));
                if (messageSend.MessageType == (uint)FilterAPI.MessageType.PRE_CREATE)
                {
                    ProcessUnitTest.controlIONotification = true;

                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));

                    //if you want to block the file access, you can return below status.
                    //messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                    //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;

                    messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                    Marshal.StructureToPtr(messageReply, replyDataPtr, true);

                    return(true);
                }

                if (messageSend.MessageType == (uint)FilterAPI.MessageType.POST_CREATE)
                {
                    ProcessUnitTest.monitorIONotification = true;
                    return(true);
                }

                FilterAPI.PROCESS_INFO processInfo = (FilterAPI.PROCESS_INFO)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.PROCESS_INFO));
                if (FilterAPI.MESSAGE_SEND_VERIFICATION_NUMBER != processInfo.VerificationNumber)
                {
                    MessageBoxHelper.PrepToCenterMessageBoxOnForm(this);
                    MessageBox.Show("Received message corrupted.Please check if the PROCESS_INFO structure is correct.");

                    EventManager.WriteMessage(139, "FilterCallback", EventLevel.Error, "Received message corrupted.Please check if the PROCESS_INFO structure is correct.");
                    return(false);
                }

                processMessage.AddMessage(processInfo);

                if (replyDataPtr.ToInt64() != 0)
                {
                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));

                    if (processInfo.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_PROCESS_CREATION_INFO)
                    {
                        //this is new process creation, you can block it here by returning the STATUS_ACCESS_DENIED.
                        messageReply.ReturnStatus = processInfo.Status;
                        Marshal.StructureToPtr(messageReply, replyDataPtr, true);
                    }
                }

                return(ret);
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterCallback", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }
        }
Пример #6
0
        public bool GetUserPermission(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            Boolean             retVal              = true;
            string              userPassword        = string.Empty;
            string              fileName            = messageSend.FileName;
            string              lastError           = string.Empty;
            string              processName         = string.Empty;
            string              userName            = string.Empty;
            bool                isFirstAccess       = false;
            CacheUserAccessInfo cacheUserAccessInfo = new CacheUserAccessInfo();

            try
            {
                FilterAPI.DecodeProcessName(messageSend.ProcessId, out processName);
                FilterAPI.DecodeUserName(messageSend.Sid, out userName);

                string index = (userName + "_" + processName + "_" + fileName).ToLower();

                //cache the same user/process/filename access.
                lock (userAccessCache)
                {
                    if (userAccessCache.ContainsKey(index))
                    {
                        cacheUserAccessInfo = userAccessCache[index];
                        EventManager.WriteMessage(446, "GetUserPermission", EventLevel.Verbose, "Thread" + Thread.CurrentThread.ManagedThreadId + ",userInfoKey " + index + " exists in the cache table.");
                    }
                    else
                    {
                        isFirstAccess                      = true;
                        cacheUserAccessInfo.index          = index;
                        cacheUserAccessInfo.lastAccessTime = DateTime.Now;
                        userAccessCache.Add(index, cacheUserAccessInfo);
                        EventManager.WriteMessage(435, "GetUserPermission", EventLevel.Verbose, "Thread" + Thread.CurrentThread.ManagedThreadId + ",add userInfoKey " + index + " to the cache table.");
                    }
                }

                //synchronize the same file access.
                if (!cacheUserAccessInfo.syncEvent.WaitOne(new TimeSpan(0, 0, (int)GlobalConfig.ConnectionTimeOut)))
                {
                    string info = "User name: " + userName + ",processname:" + processName + ",file name:" + fileName + " wait for permission timeout.";
                    EventManager.WriteMessage(402, "GetUserPermission", EventLevel.Warning, info);
                }

                TimeSpan timeSpan = DateTime.Now - cacheUserAccessInfo.lastAccessTime;

                if (!isFirstAccess && timeSpan.TotalSeconds < cacheTimeOutInSeconds)
                {
                    //the access was cached, return the last access status.
                    retVal = cacheUserAccessInfo.accessStatus;

                    string info = "thread" + Thread.CurrentThread.ManagedThreadId + ",  Cached userInfoKey " + index + " in the cache table,return " + retVal;
                    EventManager.WriteMessage(451, "GetUserPermission", EventLevel.Verbose, info);

                    return(retVal);
                }


                DRPolicyData drPolicyData = new DRPolicyData();
                retVal = GetDRPolicyDataFromDataBuffer(messageSend.DataBuffer, messageSend.Length, ref drPolicyData, ref lastError);
                if (!retVal)
                {
                    EventManager.WriteMessage(258, "GetUserPermission", EventLevel.Error, "Process encrypted file failed because of error:" + lastError);
                }
                else
                {
                    if ((drPolicyData.AESFlags & AESFlags.Flags_Enabled_Check_User_Password) == AESFlags.Flags_Enabled_Check_User_Password)
                    {
                        string messageInfo = "User name: " + userName + ",processname:" + processName + ",file name:" + fileName + "\n\n Enter password in password windows.";
                        EventManager.WriteMessage(301, "Request user password.", EventLevel.Verbose, messageInfo);

                        UserPasswordForm userPasswordForm = new UserPasswordForm(userName, processName, fileName);
                        userPasswordForm.BringToFront();
                        userPasswordForm.Focus();
                        userPasswordForm.TopMost = true;

                        if (userPasswordForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        {
                            userPassword = userPasswordForm.userPassword;
                        }
                    }

                    if ((drPolicyData.AESFlags & AESFlags.Flags_Enabled_Revoke_Access_Control) == AESFlags.Flags_Enabled_Revoke_Access_Control)
                    {
                        retVal = GetAccessPermissionFromServer(messageSend, drPolicyData, userName, processName, userPassword, ref cacheUserAccessInfo);
                    }
                    else
                    {
                        if (drPolicyData.UserPassword.Length > 0)
                        {
                            if (!string.Equals(userPassword, drPolicyData.UserPassword))
                            {
                                retVal = false;
                            }
                        }
                    }
                }

                cacheUserAccessInfo.accessStatus = retVal;
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(340, "GetUserPermission", EventLevel.Error, "filter callback exception." + ex.Message);
                retVal = false;
            }
            finally
            {
                if (!string.IsNullOrEmpty(cacheUserAccessInfo.key))
                {
                    byte[] encryptKey = Utils.ConvertHexStrToByteArray(cacheUserAccessInfo.key);
                    byte[] encryptIV  = Utils.ConvertHexStrToByteArray(cacheUserAccessInfo.iv);


                    //write the iv and key to the reply data buffer with format FilterAPI.AESDataBuffer
                    MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                    BinaryWriter bw = new BinaryWriter(ms);
                    bw.Write(encryptIV);
                    bw.Write(encryptKey.Length);
                    bw.Write(encryptKey);

                    messageReply.DataBufferLength = (uint)ms.Length;
                }

                cacheUserAccessInfo.lastAccessTime = DateTime.Now;
                cacheUserAccessInfo.syncEvent.Set();
            }

            return(retVal);
        }
        Boolean FilterCallback(IntPtr sendDataPtr, IntPtr replyDataPtr)
        {
            Boolean ret = true;

            try
            {
                FilterAPI.MessageSendData messageSend = (FilterAPI.MessageSendData)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.MessageSendData));

                if (FilterAPI.MESSAGE_SEND_VERIFICATION_NUMBER != messageSend.VerificationNumber)
                {
                    MessageBoxHelper.PrepToCenterMessageBoxOnForm(this);
                    MessageBox.Show("Received message corrupted.Please check if the MessageSendData structure is correct.");

                    EventManager.WriteMessage(139, "FilterCallback", EventLevel.Error, "Received message corrupted.Please check if the MessageSendData structure is correct.");
                    return(false);
                }

                EventManager.WriteMessage(149, "FilterCallback", EventLevel.Verbose, "Received message Id#" + messageSend.MessageId + " type:" + messageSend.MessageType
                                          + " CreateOptions:" + messageSend.CreateOptions.ToString("X") + " infoClass:" + messageSend.InfoClass + " fileName:" + messageSend.FileName);

                filterMessage.AddMessage(messageSend);

                FileProtectorUnitTest.FileIOEventHandler(messageSend);

                if (replyDataPtr.ToInt64() != 0)
                {
                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));

                    //if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_PROCESS_TERMINATION_INFO)
                    //{
                    //    //the process termination callback, you can get the notification if you register the callback setting of the process filter.
                    //}

                    if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_PROCESS_CREATION_INFO)
                    {
                        //this is new process creation, you can block it here by returning the STATUS_ACCESS_DENIED, below is the process information
                        FilterAPI.PROCESS_INFO processInfo = (FilterAPI.PROCESS_INFO)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.PROCESS_INFO));

                        messageReply.ReturnStatus = processInfo.Status;
                        Marshal.StructureToPtr(messageReply, replyDataPtr, true);
                    }
                    else if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_ENCRYPTION_IV_AND_KEY)
                    {
                        //this is encryption filter rule with boolean config "REQUEST_ENCRYPT_KEY_AND_IV_FROM_SERVICE" enabled.
                        //the filter driver request the IV and key to open or create the encrypted file.

                        //if you want to deny the file open or creation, you set the value as below:
                        //messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;

                        EventManager.WriteMessage(200, "filtercallback", EventLevel.Verbose, messageSend.FileName + " FILTER_REQUEST_ENCRYPTION_IV_AND_KEY");

                        //Here we return the test iv and key to the filter driver, you need to replace with you own iv and key in your code.
                        AESDataBuffer aesData = new AESDataBuffer();
                        aesData.AccessFlags         = FilterAPI.ALLOW_MAX_RIGHT_ACCESS;
                        aesData.IV                  = FilterAPI.DEFAULT_IV_TAG;
                        aesData.IVLength            = (uint)aesData.IV.Length;
                        aesData.EncryptionKey       = Utils.GetKeyByPassPhrase(DigitalRightControl.PassPhrase);
                        aesData.EncryptionKeyLength = (uint)aesData.EncryptionKey.Length;

                        byte[] aesDataArray = DigitalRightControl.ConvertAESDataToByteArray(aesData);
                        messageReply.DataBufferLength = (uint)aesDataArray.Length;
                        Array.Copy(aesDataArray, messageReply.DataBuffer, aesDataArray.Length);

                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                    }
                    else if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_ENCRYPTION_IV_AND_KEY_AND_TAGDATA)
                    {
                        //this is encryption filter rule with boolean config "REQUEST_ENCRYPT_KEY_IV_AND_TAGDATA_FROM_SERVICE" enabled.
                        //the filter driver request the IV and key to open or create the encrypted file.

                        //if you want to deny the file open or creation, you set the value as below:
                        //messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;

                        if (messageSend.DataBufferLength > 0)
                        {
                            //this is the tag data which attached to the encrypted file .
                            string tagDataStr = Encoding.Unicode.GetString(messageSend.DataBuffer);
                            EventManager.WriteMessage(235, "filtercallback", EventLevel.Verbose, "EncryptedFile:" + messageSend.FileName + ",tagData:" + tagDataStr);
                        }

                        //Here we return the test iv ,key and tag data to the filter driver, you need to replace with you own iv and key in your code.
                        AESDataBuffer aesData = new AESDataBuffer();
                        aesData.AccessFlags         = FilterAPI.ALLOW_MAX_RIGHT_ACCESS;
                        aesData.IV                  = FilterAPI.DEFAULT_IV_TAG;
                        aesData.IVLength            = (uint)aesData.IV.Length;
                        aesData.EncryptionKey       = Utils.GetKeyByPassPhrase(DigitalRightControl.PassPhrase);
                        aesData.EncryptionKeyLength = (uint)aesData.EncryptionKey.Length;
                        aesData.TagData             = Encoding.Unicode.GetBytes("TagData:" + messageSend.FileName);
                        aesData.TagDataLength       = (uint)aesData.TagData.Length;

                        byte[] aesDataArray = DigitalRightControl.ConvertAESDataToByteArray(aesData);
                        messageReply.DataBufferLength = (uint)aesDataArray.Length;
                        Array.Copy(aesDataArray, messageReply.DataBuffer, aesDataArray.Length);

                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                    }
                    else
                    {
                        //this is for control filter driver when the pre-IO was registered.

                        //here you can control the IO behaviour and modify the data.
                        if (!FileProtectorUnitTest.UnitTestCallbackHandler(messageSend) || !FilterService.AuthorizeFileAccess(messageSend, ref messageReply))
                        {
                            //to comple the PRE_IO
                            messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                            messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;

                            EventManager.WriteMessage(160, "FilterCallback", EventLevel.Error, "Return error for I/O request:" + ((FilterAPI.MessageType)messageSend.MessageType).ToString() +
                                                      ",fileName:" + messageSend.FileName);
                        }
                        else
                        {
                            messageReply.MessageId    = messageSend.MessageId;
                            messageReply.MessageType  = messageSend.MessageType;
                            messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                        }
                    }

                    Marshal.StructureToPtr(messageReply, replyDataPtr, true);
                }

                return(ret);
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterCallback", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }
        }
Пример #8
0
        static public bool GetFileAccessPermission(ref FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            Boolean retVal      = true;
            string  fileName    = messageSend.FileName;
            string  lastError   = string.Empty;
            string  processName = string.Empty;
            string  userName    = string.Empty;
            string  encryptKey  = string.Empty;


            try
            {
                FilterAPI.DecodeProcessName(messageSend.ProcessId, out processName);
                FilterAPI.DecodeUserName(messageSend.Sid, out userName);

                //by default the tag data format is "accountName;ivStr"

                int    tagDataLength = (int)messageSend.DataBufferLength;
                byte[] tagData       = messageSend.DataBuffer;
                Array.Resize(ref tagData, tagDataLength);

                string tagStr = UnicodeEncoding.Unicode.GetString(tagData);

                int    index = tagStr.IndexOf(";");
                byte[] iv    = tagData;

                if (index > 0)
                {
                    string serverAccount = tagStr.Substring(0, index);
                    string ivStr         = tagStr.Substring(index + 1);
                    iv = Utils.ConvertHexStrToByteArray(ivStr);
                }

                uint accessFlag = 0;

                retVal = IsFileAccessAuthorized(fileName,
                                                userName,
                                                processName,
                                                tagStr,
                                                ref encryptKey,
                                                ref accessFlag,
                                                ref lastError);

                if (retVal && !string.IsNullOrEmpty(encryptKey))
                {
                    byte[] keyArray = Utils.ConvertHexStrToByteArray(encryptKey);

                    //write the iv and key to the reply data buffer with format FilterAPI.AESDataBuffer
                    AESDataBuffer aesData = new AESDataBuffer();
                    if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_ENCRYPTION_IV_AND_KEY_AND_ACCESSFLAG)
                    {
                        aesData.AccessFlags = FilterAPI.ALLOW_MAX_RIGHT_ACCESS;
                    }
                    else
                    {
                        aesData.AccessFlags = FilterAPI.ALLOW_MAX_RIGHT_ACCESS;
                    }
                    aesData.IV                  = iv;
                    aesData.IVLength            = (uint)iv.Length;
                    aesData.EncryptionKey       = keyArray;
                    aesData.EncryptionKeyLength = (uint)keyArray.Length;

                    byte[] aesDataArray = DigitalRightControl.ConvertAESDataToByteArray(aesData);
                    messageReply.DataBufferLength = (uint)aesDataArray.Length;
                    Array.Copy(aesDataArray, messageReply.DataBuffer, aesDataArray.Length);

                    messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                }
            }
            catch (Exception ex)
            {
                lastError = "GetFileAccessPermission exception." + ex.Message;
                EventManager.WriteMessage(340, "GetFileAccessPermission", EventLevel.Error, lastError);
                retVal = false;
            }

            if (!retVal)
            {
                byte[] errorBuffer = UnicodeEncoding.Unicode.GetBytes(lastError);
                Array.Copy(errorBuffer, messageSend.DataBuffer, errorBuffer.Length);

                messageSend.DataBufferLength = (uint)errorBuffer.Length;
            }


            return(retVal);
        }
        private bool FilterRequestHandler(ref FilterAPI.MessageSendData messageSend, IntPtr replyDataPtr)
        {
            Boolean retVal    = true;
            string  fileName  = messageSend.FileName;
            string  lastError = string.Empty;

            try
            {
                if ((replyDataPtr.ToInt64() != 0))
                {
                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));
                    messageReply.MessageId   = messageSend.MessageId;
                    messageReply.MessageType = messageSend.MessageType;

                    if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_USER_PERMIT ||
                        messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_ENCRYPTION_IV_AND_KEY)
                    {
                        if (null == digitalRightsManagement)
                        {
                            digitalRightsManagement = new DRM();
                        }

                        //get permission for secure shared file
                        retVal = digitalRightsManagement.GetUserPermission(messageSend, ref messageReply);
                    }
                    else
                    {
                        //control the file I/O here
                        retVal = FilterService.IOAccessControl(messageSend, ref messageReply);
                    }

                    if (retVal)
                    {
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                    }
                    else
                    {
                        //comple the PRE_CREATE,user get access denied for the file open.
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                    }

                    Marshal.StructureToPtr(messageReply, replyDataPtr, true);

                    if (!retVal)
                    {
                        messageSend.Status = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                    }
                }


                filterMessage.AddMessage(messageSend);

                return(retVal);
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterRequestHandler", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }
        }
        Boolean FilterCallback(IntPtr sendDataPtr, IntPtr replyDataPtr)
        {
            Boolean ret = true;

            try
            {
                FilterAPI.MessageSendData messageSend = (FilterAPI.MessageSendData)Marshal.PtrToStructure(sendDataPtr, typeof(FilterAPI.MessageSendData));

                if (FilterAPI.MESSAGE_SEND_VERIFICATION_NUMBER != messageSend.VerificationNumber)
                {
                    MessageBoxHelper.PrepToCenterMessageBoxOnForm(this);
                    MessageBox.Show("Received message corrupted.Please check if the MessageSendData structure is correct.");

                    EventManager.WriteMessage(139, "FilterCallback", EventLevel.Error, "Received message corrupted.Please check if the MessageSendData structure is correct.");
                    return(false);
                }

                EventManager.WriteMessage(149, "FilterCallback", EventLevel.Verbose, "Received message Id#" + messageSend.MessageId + " type:" + messageSend.MessageType
                                          + " CreateOptions:" + messageSend.CreateOptions.ToString("X") + " infoClass:" + messageSend.InfoClass + " fileName:" + messageSend.FileName);

                filterMessage.AddMessage(messageSend);

                FileProtectorUnitTest.FileIOEventHandler(messageSend);

                if (replyDataPtr.ToInt64() != 0)
                {
                    FilterAPI.MessageReplyData messageReply = (FilterAPI.MessageReplyData)Marshal.PtrToStructure(replyDataPtr, typeof(FilterAPI.MessageReplyData));

                    //here you can control the IO behaviour and modify the data.
                    if (!FileProtectorUnitTest.UnitTestCallbackHandler(messageSend) || !FilterService.IOAccessControl(messageSend, ref messageReply))
                    {
                        //to comple the PRE_IO
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_ACCESS_DENIED;
                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;

                        EventManager.WriteMessage(160, "FilterCallback", EventLevel.Error, "Return error for I/O request:" + ((FilterAPI.MessageType)messageSend.MessageType).ToString() +
                                                  ",fileName:" + messageSend.FileName);
                    }
                    else
                    {
                        messageReply.MessageId    = messageSend.MessageId;
                        messageReply.MessageType  = messageSend.MessageType;
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;
                    }

                    Marshal.StructureToPtr(messageReply, replyDataPtr, true);
                }

                string info = "FileProtector process request " + FilterMessage.FormatIOName(messageSend) + ",pid:" + messageSend.ProcessId +
                              " ,filename:" + messageSend.FileName + ",return status:" + FilterMessage.FormatStatus(messageSend.Status);

                if (messageSend.Status == (uint)NtStatus.Status.Success)
                {
                    ret = false;
                    EventManager.WriteMessage(98, "FilterCallback", EventLevel.Verbose, info);
                }
                else
                {
                    ret = true;
                    EventManager.WriteMessage(98, "FilterCallback", EventLevel.Error, info);
                }

                return(ret);
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(134, "FilterCallback", EventLevel.Error, "filter callback exception." + ex.Message);
                return(false);
            }
        }
Пример #11
0
        public static bool AuthorizeRegistryAccess(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            bool ret = true;

            try
            {
                messageReply.MessageId    = messageSend.MessageId;
                messageReply.MessageType  = messageSend.MessageType;
                messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;


                //
                //here you can control registry request,block the access or modify the registry data.
                //
                //

                //if you don't want to change anything to this registry request, just let it pass through as below setting:
                //messageReply.FilterStatus = 0;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                //if you want to block the access this registry request, you can return the status as below,
                //it is only for pre callback requests.
                //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;

                //if you want to modify the registry data and complete the pre IO with your own data, you can return status as below:
                // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                // messageReply.DataBufferLength = the return data buffer length.
                // messageReply.DataBuffer = the data you want to return.
                // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                FilterAPI.RegCallbackClass regCallbackClass = (FilterAPI.RegCallbackClass)messageSend.Offset;

                uint   dataLength = messageSend.DataBufferLength;
                byte[] data       = messageSend.DataBuffer;

                switch (regCallbackClass)
                {
                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    IntPtr keyValueInfoPtr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);


                    if (messageSend.FileName.IndexOf("EaseFilter") <= 0)
                    {
                        //this is not our unit test key
                        break;
                    }

                    //below code is for unit test to demo how to complete pre-callback registry call with our own data.
                    EventManager.WriteMessage(400, "AuthorizeRegistryAccess", EventLevel.Error, "Reg_Pre_Query_Value_Key keyValuseInformationClass:" + keyValuseInformationClass.ToString());

                    switch (keyValuseInformationClass)
                    {
                    case KEY_VALUE_INFORMATION_CLASS.KeyValueBasicInformation:
                    {
                        //public struct KEY_VALUE_BASIC_INFORMATION
                        // {
                        //     public uint TitleIndex;
                        //     public uint Type;
                        //     public uint NameLength;
                        //     public byte[] Name;
                        // }

                        uint   titleIndex      = 0;
                        uint   type            = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        byte[] valueName       = Encoding.Unicode.GetBytes("value1");
                        uint   valueNameLength = (uint)valueName.Length;

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);
                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(valueNameLength);
                        bw.Write(valueName);

                        messageReply.DataBufferLength = (uint)ms.Position;
                        messageReply.FilterStatus     = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;


                        break;
                    }

                    case KEY_VALUE_INFORMATION_CLASS.KeyValueFullInformation:
                    {
                        //KeyValueFullInformation class structure
                        //public uint TitleIndex;
                        //public uint Type;
                        //public uint DataOffset;
                        //public uint DataLength;
                        //public uint NameLength;
                        //public byte[] Name;

                        uint   titleIndex      = 0;
                        uint   type            = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        uint   testData        = 12345;
                        uint   testDataLength  = sizeof(uint);
                        byte[] valueName       = Encoding.Unicode.GetBytes("value1");
                        uint   valueNameLength = (uint)valueName.Length;
                        uint   dataOffset      = 5 * sizeof(uint) + valueNameLength;

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);
                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(dataOffset);
                        bw.Write(testDataLength);
                        bw.Write(valueNameLength);
                        bw.Write(valueName);
                        bw.Write(testData);

                        messageReply.DataBufferLength = (uint)ms.Position;
                        messageReply.FilterStatus     = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;


                        break;
                    }

                    case KEY_VALUE_INFORMATION_CLASS.KeyValuePartialInformation:
                    {
                        // public struct KEY_VALUE_PARTIAL_INFORMATION
                        //{
                        //    public uint TitleIndex;
                        //    public uint Type;
                        //    public uint DataLength;
                        //    public byte[] Data;
                        //}

                        uint titleIndex     = 0;
                        uint type           = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        uint testData       = 12345;
                        uint testDataLength = sizeof(uint);

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);

                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(testDataLength);
                        bw.Write(testData);

                        messageReply.DataBufferLength = (uint)ms.Position;

                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;

                        break;
                    }


                    default: break;
                    }
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Pre_Open_KeyEx:
                {
                    //this is our unit test key
                    if (messageSend.FileName.IndexOf("EaseFilter") > 0)
                    {
                        //NOT allow to create new registry key.

                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                    }

                    break;
                }

                default: break;
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(400, "AuthorizeRegistryAccess", EventLevel.Error, "AuthorizeRegistryAccess exception:" + ex.Message);
            }

            return(ret);
        }