diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/kerneltest/f32test/plugins/version_1/virus/t_vshook.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/kerneltest/f32test/plugins/version_1/virus/t_vshook.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,685 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// f32test\virus\t_vshook.cpp +// +// + +#include "t_vshook.h" +#include + + +_LIT(KVirusScannerName, "This is a test virus scanner"); + + +/** +Leaving New function for the plugin +@internalComponent +*/ +CTestVirusHook* CTestVirusHook::NewL() + { + return new(ELeave) CTestVirusHook; + } + + +/** +Constructor for the plugin +@internalComponent +*/ +CTestVirusHook::CTestVirusHook() + { +// RDebug::Print(_L("EMaxClientOperations %d, size of CFsPlugin %d, iSignatureOffset %d"), EMaxClientOperations, sizeof(CFsPlugin), _FOFF(CTestVirusHook, iSignature)); + ASSERT(iSignature == 0); + iSignature = 0x1234; + } + + +/** +The destructor for the test virus scanner hook. This would +not be a part of a normal virus scanner implementation as +normal virus scanners cannot be unloaded - it must be +provided in the test virus scanner server so that it can +be tested with the F32 test suite. +@internalComponent +*/ +CTestVirusHook::~CTestVirusHook() + { + iFs.Close(); + + for (TInt i = 0; i < iSignaturesLoaded; i++) + { + if (iKnownSignatures[i]) + { + delete iKnownSignatures[i]; + } + } + ASSERT(iSignature == 0x1234); + } + +/** +Initialise the virus scanner. +Reads the virus definition file and then waits for +notification that files containing a virus have been +detected. +@internalComponent +*/ +void CTestVirusHook::InitialiseL() + { + User::LeaveIfError(RegisterIntercept(EFsFileOpen, EPreIntercept)); + User::LeaveIfError(RegisterIntercept(EFsFileSubClose, EPostIntercept)); + User::LeaveIfError(RegisterIntercept(EFsFileRename, EPreIntercept)); + User::LeaveIfError(RegisterIntercept(EFsRename, EPreIntercept)); + User::LeaveIfError(RegisterIntercept(EFsDelete, EPreIntercept)); + User::LeaveIfError(RegisterIntercept(EFsReplace, EPreIntercept)); + User::LeaveIfError(RegisterIntercept(EFsReadFileSection, EPreIntercept)); + + ReadVirusDefinitionFile(); + } + +/** +Read the virus definition file C:\virusdef.txt and parse +its contents. Any virus definitions found in that file +are added to the KnownSignatures array so they can be +used by the virus scanning hook. + +@internalComponent + +@return KErrNone if the file was read and parsed +successfuly. +*/ +TInt CTestVirusHook::ReadVirusDefinitionFile() + { + TInt r = iFs.Connect(); + if (r != KErrNone) + return r; + + r = iFs.SetNotifyChange(EFalse); // Disable change notifications + if (r != KErrNone) + return r; + + //Open the virus definition file + RFile vsDefFile; + r = vsDefFile.Open(iFs, _L("C:\\virusdef.txt"), EFileShareAny); + if (r != KErrNone) + return r; + + TInt fileSize=0; + r = vsDefFile.Size(fileSize); + if (r != KErrNone) + { + vsDefFile.Close(); + return r; + } + + HBufC8* defBuf=NULL; + + TRAP(r,defBuf = HBufC8::NewL(fileSize)); + if (r != KErrNone) + { + vsDefFile.Close(); + return r; + } + + TPtr8 ptr(defBuf->Des()); + r = vsDefFile.Read(ptr); + if (r != KErrNone) + { + delete defBuf; + vsDefFile.Close(); + return r; + } + + //Now parse the definition file, putting the definitions into the hook's + //array of known virus signatures. + TInt bytesParsed = 0; + TInt stringBeginPos = 0; + TInt stringEndPos = 0; + TInt stringLength = 0; + HBufC8* signatureBuf = NULL; + while (bytesParsed < fileSize) + { + ptr.Set(defBuf->Des()); + ptr.Set(&ptr[bytesParsed], fileSize-bytesParsed, fileSize-bytesParsed); + stringBeginPos = ptr.MatchF(_L8("startdef:*:enddef*")); + + if (stringBeginPos < 0) + { + break; + } + + stringBeginPos += 9; //stardef: + stringBeginPos += bytesParsed; + ptr.Set(defBuf->Des()); + ptr.Set(&ptr[stringBeginPos], fileSize-stringBeginPos, fileSize-stringBeginPos); + stringEndPos = ptr.MatchF(_L8("*:enddef*")); + + if (stringEndPos < 0) + { + break; + } + + stringEndPos += 9; //stardef: + stringEndPos += bytesParsed; + stringLength = stringEndPos - stringBeginPos; + + ptr.Set(defBuf->Des()); + TRAP(r,signatureBuf = HBufC8::NewL(stringLength)); + + TPtrC8 actualSig(ptr.Mid(stringBeginPos, stringLength)); + + TPtr8 ptr2(signatureBuf->Des()); + ptr2.Append(actualSig); + iKnownSignatures[iSignaturesLoaded] = signatureBuf; + iSignaturesLoaded++; + + bytesParsed += 9; //startdef: + bytesParsed += stringLength; + bytesParsed += 9; //:enddef\n + } + + //Cleanup + delete defBuf; + vsDefFile.Close(); + + return r; + } + +/** +@internalComponent +*/ +TInt CTestVirusHook::DoRequestL(TFsPluginRequest& aRequest) + { + TInt err = KErrNotSupported; + + TInt function = aRequest.Function(); + + iDrvNumber = aRequest.DriveNumber(); + + switch(function) + { + case EFsFileOpen: + err = VsFileOpen(aRequest); + break; + + case EFsFileSubClose: + VsFileClose(aRequest); + break; + + case EFsFileRename: + case EFsRename: + case EFsReplace: + err = VsFileRename(aRequest); + break; + + case EFsDelete: + err = VsFileDelete(aRequest); + break; + + case EFsReadFileSection: + err = VsReadFileSection(aRequest); + break; + + default: + break; + } + + return err; + } + + +/** +@internalComponent +*/ +TInt CTestVirusHook::VsFileOpen(TFsPluginRequest& aRequest) + { + TFileName fileName; + TInt err = ValidateRequest(aRequest, fileName); + if (err == KErrNone) + { + err = ScanFile(fileName); + if (err != KErrNone) + { + // Clean the infected file + CleanFile(fileName, EFileOpen); + } + } + + return err; + } + +/** +@internalComponent +*/ +void CTestVirusHook::VsFileClose(TFsPluginRequest& aRequest) + { + TFileName fileName; + TInt err = GetName(&aRequest, fileName); + if(err == KErrNone) + { + err = ScanFile(fileName); + if (err != KErrNone) + { + // Clean the infected file + CleanFile(fileName, EFileClose); + } + } + } + +/** +@internalComponent +*/ +TInt CTestVirusHook::VsFileRename(TFsPluginRequest& aRequest) + { + + TInt err = VsDirRename(aRequest); + if(err != KErrAccessDenied) + { + TFileName fileName; + err = ValidateRequest(aRequest, fileName); + if (err == KErrNone) + { + err = ScanFile(fileName); + if (err != KErrNone) + { + // Clean the infected file + CleanFile(fileName, EFileRename); + } + } + } + + return err; + } + +/** +@internalComponent +*/ +TInt CTestVirusHook::VsDirRename(TFsPluginRequest& aRequest) + { + + TFileName fileName; + TInt err = GetName(&aRequest, fileName); + if(err != KErrNone) + return(err); + + err = fileName.Find(_L("\\system\\lib\\")); + if (err != KErrNotFound) + { + //Don't allow sys\bin to be ever renamed + return KErrAccessDenied; + } + err = fileName.Find(_L("\\sys\\bin\\")); + if (err != KErrNotFound) + { + //Don't allow sys\bin to be ever renamed + return KErrAccessDenied; + } + + return err; + } + +/** +@internalComponent +*/ +TInt CTestVirusHook::VsFileDelete(TFsPluginRequest& aRequest) + { + + TFileName fileName; + TInt err = ValidateRequest(aRequest, fileName); + return err; + } + +/** +@internalComponent +*/ +TInt CTestVirusHook::VsReadFileSection(TFsPluginRequest& aRequest) + { + + // The t_virus test uses a filename clean.txt, a read length of 8 and a read position of 0. + TFileName fileName; + TInt len; + TInt pos; + + // test getting name on read file section intercept + TInt err = GetName(&aRequest, fileName); + if(err != KErrNone) + { + return(err); + } + TParse parse; + parse.Set(fileName,NULL,NULL); + TPtrC name = parse.Name(); + if(name.CompareF(_L("clean"))!=0) + { + return(KErrGeneral); + } + TPtrC ext = parse.Ext(); + if(ext.CompareF(_L(".txt"))!=0) + { + return(KErrGeneral); + } + + // test getting read length and required file position on read file section intercept + err = GetFileAccessInfo(&aRequest, len, pos); + if(err != KErrNone) + { + return(err); + } + if ((len != 8) || (pos != 0)) + { + return(KErrGeneral); + } + + return KErrNone; + } + + +/** +@internalComponent +*/ +TInt CTestVirusHook::VirusScannerName(TDes& aName) + { + aName = KVirusScannerName; + return KErrNone; + } + +/** +Reads the contents of the file passed in and checks +whether it contains any of the specified virus +signatures + +@return A value depending on whether a known virus is +found within the file. + +@param aFile A CFileCB object which can be used to read the file. +@internalComponent +*/ +TInt CTestVirusHook::ScanFile(const TDesC& aName) + { + + TInt r = KErrNone; + TInt pos = 0; + TInt size = 0; + + // Rename the file + TPtrC tmpFile = _L("VS_RENAMED.VSH"); + TParse parse; + parse.Set(aName, NULL, NULL); + parse.Set(parse.DriveAndPath(), &tmpFile, NULL); + + r = iFs.Rename(aName, parse.FullName()); + if(r != KErrNone) + return r; + + RFile file; + r = file.Open(iFs, parse.FullName(), EFileRead); + if(r == KErrNone) + { + r = file.Size(size); + } + + //If the file size is 0, then the file + //has just been created - so it can't contain + //a virus. + if(r != KErrNone || size == 0) + { + file.Close(); + + // Rename the file back + TInt err = iFs.Rename(parse.FullName(), aName); + if(err != KErrNone) + return err; + + return r; + } + + do + { + r = file.Read(pos, iScanBuf); + + if (r != KErrNone) + { + break; + } + + r = ScanBuffer(); + pos += iScanBuf.Length(); + } while ((r == KErrNotFound) && (iScanBuf.Length() == iScanBuf.MaxLength())); + + file.Close(); + + // Rename the file back + TInt err = iFs.Rename(parse.FullName(), aName); + if(err != KErrNone) + return err; + + if (r > 0) + { + //We've found an infection + return KErrAccessDenied; + } + else + { + return KErrNone; + } + } + +/** +Scans the internal buffer which has been loaded with fresh +file contents, to see if it contains any known virus +signatures. + +@return A value depending on whether a known virus signature +is found within the buffer. + +@internalComponent +*/ +TInt CTestVirusHook::ScanBuffer() + { + //Look through the internal buffer for all known virus signatures. + + TInt r; + for (TInt i = 0; i < iSignaturesLoaded; i++) + { + r = iScanBuf.Find(iKnownSignatures[i]->Des()); + + if (r != KErrNotFound) + { + return r; + } + } + return KErrNone; + } + +/** +Validate that nobody is trying to touch the virus scanner files. + +@internalComponent + +@return A value depending on whethe the virus scanner files are +being fiddled with. + +@param aDriveNum The drive number of the request which called into +the test virus scanning hook. + +@param aName The full pathname of the file being accessed by the +request to the file server hook. +*/ +TInt CTestVirusHook::ValidateRequest(TFsPluginRequest& aRequest, TFileName& aFileName) + { + TInt driveNumber = aRequest.DriveNumber(); + + TInt err = GetName(&aRequest, aFileName); + if(err != KErrNone) + return(err); + + if (driveNumber == EDriveC) + { + TInt r = aFileName.Find(_L("\\virusdef.txt")); + + if (r != KErrNotFound) + { + //Do not allow the deletion of the virus definition file. + return KErrAccessDenied; + } + + r = aFileName.Find(_L("\\system\\libs\\t_vshook.pxt")); + if (r != KErrNotFound) + { + //Do not allow the deletion of the this dll + return KErrAccessDenied; + } + r = aFileName.Find(_L("\\sys\\bin\\t_vshook.pxt")); + if (r != KErrNotFound) + { + //Do not allow the deletion of the this dll + return KErrAccessDenied; + } + } + return KErrNone; + } + +/** +Processes a message which describes the detection of an +infected file. Appends the relevant text at the end of the +file to say that it has been "cleaned". This allows the virus +test program to confirm that the test virus scanner is +behaving as expected. + +@internalComponent +@param aMessage The message to be processed. +*/ +void CTestVirusHook::CleanFile(const TDesC& aName, TInt aOperation) + { + + RFile infectedFile; + TBool bChangedToRw=EFalse; + TInt pos=0; + + TUint fileAtt; + TInt r = iFs.Att(aName, fileAtt); + if (r != KErrNone) + { + return; + } + + if (fileAtt & KEntryAttReadOnly) + { + bChangedToRw = ETrue; + r = iFs.SetAtt(aName, 0, KEntryAttReadOnly); + } + + r = infectedFile.Open(iFs, aName, EFileShareAny | EFileWrite); + + if (r != KErrNone) + { + return; + } + + //To show we've fixed the file, append "Infection deleted" to the end of it. + infectedFile.Seek(ESeekEnd, pos); + switch (aOperation) + { + case EFileOpen: + infectedFile.Write(_L8("infection detected - file open\\n")); + break; + case EFileDelete: + infectedFile.Write(_L8("infection detected - file delete\\n")); + break; + case EFileRename: + infectedFile.Write(_L8("infection detected - file rename\\n")); + break; + case EFileClose: + infectedFile.Write(_L8("infection detected - file close\\n")); + break; + } + + infectedFile.Close(); + + if (bChangedToRw) + { + iFs.SetAtt(aName, KEntryAttReadOnly,0); + } + } + +//factory functions + +class CVsHookFactory : public CFsPluginFactory + { +public: + CVsHookFactory(); + virtual TInt Install(); + virtual CFsPlugin* NewPluginL(); + virtual CFsPlugin* NewPluginConnL(); + virtual TInt UniquePosition(); + }; + +/** +Constructor for the plugin factory +@internalComponent +*/ +CVsHookFactory::CVsHookFactory() + { + } + +/** +Install function for the plugin factory +@internalComponent +*/ +TInt CVsHookFactory::Install() + { + iSupportedDrives = KPluginAutoAttach; + + _LIT(KVsHookName,"VsHook"); + return(SetName(&KVsHookName)); + } + +/** +@internalComponent +*/ +TInt CVsHookFactory::UniquePosition() + { + return(0x3EC); + } + +/** +Plugin factory function +@internalComponent +*/ +CFsPlugin* CVsHookFactory::NewPluginL() + + { + return CTestVirusHook::NewL(); + } + +/** +Plugin factory function +@internalComponent +*/ +CFsPlugin* CVsHookFactory::NewPluginConnL() + + { + return CTestVirusHook::NewL(); + } + +/** +Create a new Plugin +@internalComponent +*/ +extern "C" { + +EXPORT_C CFsPluginFactory* CreateFileSystem() + { + return(new CVsHookFactory()); + } +} +