os/kernelhwsrv/kerneltest/f32test/plugins/version_1/virus/t_vshook.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32test\virus\t_vshook.cpp
    15 // 
    16 //
    17 
    18 #include "t_vshook.h"
    19 #include <f32pluginutils.h>
    20 
    21 
    22 _LIT(KVirusScannerName, "This is a test virus scanner");
    23 
    24 
    25 /**
    26 Leaving New function for the plugin
    27 @internalComponent
    28 */
    29 CTestVirusHook* CTestVirusHook::NewL()
    30 	{
    31 	return new(ELeave) CTestVirusHook;
    32 	}
    33 
    34 
    35 /**
    36 Constructor for the plugin
    37 @internalComponent
    38 */
    39 CTestVirusHook::CTestVirusHook()
    40 	{
    41 //	RDebug::Print(_L("EMaxClientOperations %d, size of CFsPlugin %d, iSignatureOffset %d"), EMaxClientOperations, sizeof(CFsPlugin), _FOFF(CTestVirusHook, iSignature));
    42 	ASSERT(iSignature == 0);
    43 	iSignature = 0x1234;
    44 	}
    45 
    46 
    47 /**
    48 The destructor for the test virus scanner hook.  This would
    49 not be a part of a normal virus scanner implementation as
    50 normal virus scanners cannot be unloaded - it must be 
    51 provided in the test virus scanner server so that it can
    52 be tested with the F32 test suite.
    53 @internalComponent
    54 */
    55 CTestVirusHook::~CTestVirusHook()
    56 	{
    57 	iFs.Close();
    58 
    59 	for (TInt i = 0; i < iSignaturesLoaded; i++)
    60 		{
    61 		if (iKnownSignatures[i])
    62 			{
    63 			delete iKnownSignatures[i];
    64 			}
    65 		}
    66 	ASSERT(iSignature == 0x1234);
    67 	}
    68 
    69 /**
    70 Initialise the virus scanner.
    71 Reads the virus definition file and then waits for
    72 notification that files containing a virus have been
    73 detected.
    74 @internalComponent
    75 */
    76 void CTestVirusHook::InitialiseL()
    77 	{
    78 	User::LeaveIfError(RegisterIntercept(EFsFileOpen,			EPreIntercept));
    79 	User::LeaveIfError(RegisterIntercept(EFsFileSubClose,		EPostIntercept));
    80 	User::LeaveIfError(RegisterIntercept(EFsFileRename,			EPreIntercept));
    81 	User::LeaveIfError(RegisterIntercept(EFsRename,				EPreIntercept));
    82 	User::LeaveIfError(RegisterIntercept(EFsDelete,				EPreIntercept));
    83 	User::LeaveIfError(RegisterIntercept(EFsReplace,			EPreIntercept));
    84 	User::LeaveIfError(RegisterIntercept(EFsReadFileSection,	EPreIntercept));
    85 
    86 	ReadVirusDefinitionFile();
    87 	}
    88 
    89 /**
    90 Read the virus definition file C:\virusdef.txt and parse
    91 its contents.  Any virus definitions found in that file
    92 are added to the KnownSignatures array so they can be
    93 used by the virus scanning hook.
    94 
    95 @internalComponent
    96 
    97 @return KErrNone if the file was read and parsed
    98 successfuly.
    99 */
   100 TInt CTestVirusHook::ReadVirusDefinitionFile()
   101 	{
   102 	TInt r = iFs.Connect();
   103 	if (r != KErrNone)
   104 		return r;
   105 	
   106 	r = iFs.SetNotifyChange(EFalse);	// Disable change notifications
   107 	if (r != KErrNone)
   108 		return r;
   109 	
   110 	//Open the virus definition file
   111 	RFile vsDefFile;
   112 	r = vsDefFile.Open(iFs, _L("C:\\virusdef.txt"), EFileShareAny);
   113 	if (r != KErrNone)
   114 		return r;
   115 	
   116 	TInt fileSize=0;
   117 	r = vsDefFile.Size(fileSize);
   118 	if (r != KErrNone)
   119 		{
   120 		vsDefFile.Close();
   121 		return r;
   122 		}
   123 
   124 	HBufC8* defBuf=NULL;
   125 	
   126 	TRAP(r,defBuf = HBufC8::NewL(fileSize));
   127 	if (r != KErrNone)
   128 		{
   129 		vsDefFile.Close();
   130 		return r;
   131 		}
   132 
   133 	TPtr8 ptr(defBuf->Des());
   134 	r = vsDefFile.Read(ptr);
   135 	if (r != KErrNone)
   136 		{
   137 		delete defBuf;
   138 		vsDefFile.Close();
   139 		return r;
   140 		}
   141 
   142 	//Now parse the definition file, putting the definitions into the hook's
   143 	//array of known virus signatures.
   144 	TInt bytesParsed     = 0;
   145 	TInt stringBeginPos  = 0;
   146 	TInt stringEndPos    = 0;
   147 	TInt stringLength    = 0;
   148 	HBufC8* signatureBuf = NULL;
   149 	while (bytesParsed < fileSize)
   150 		{
   151 		ptr.Set(defBuf->Des());
   152 		ptr.Set(&ptr[bytesParsed], fileSize-bytesParsed, fileSize-bytesParsed);
   153 		stringBeginPos = ptr.MatchF(_L8("startdef:*:enddef*"));
   154 
   155 		if (stringBeginPos < 0)
   156 			{
   157 			break;
   158 			}
   159 
   160 		stringBeginPos += 9; //stardef:
   161 		stringBeginPos += bytesParsed;
   162 		ptr.Set(defBuf->Des());
   163 		ptr.Set(&ptr[stringBeginPos], fileSize-stringBeginPos, fileSize-stringBeginPos);
   164 		stringEndPos = ptr.MatchF(_L8("*:enddef*"));
   165 
   166 		if (stringEndPos < 0)
   167 			{
   168 			break;
   169 			}
   170 
   171 		stringEndPos += 9; //stardef:
   172 		stringEndPos += bytesParsed;
   173 		stringLength = stringEndPos - stringBeginPos;
   174 
   175 		ptr.Set(defBuf->Des());
   176 		TRAP(r,signatureBuf = HBufC8::NewL(stringLength));
   177 		
   178 		TPtrC8 actualSig(ptr.Mid(stringBeginPos, stringLength));
   179 		
   180 		TPtr8 ptr2(signatureBuf->Des());
   181 		ptr2.Append(actualSig);
   182 		iKnownSignatures[iSignaturesLoaded] = signatureBuf;
   183 		iSignaturesLoaded++;
   184 
   185 		bytesParsed += 9; //startdef:
   186 		bytesParsed += stringLength;
   187 		bytesParsed += 9; //:enddef\n
   188 		}
   189 
   190 	//Cleanup
   191 	delete defBuf;
   192 	vsDefFile.Close();
   193 
   194 	return r;
   195 	}
   196 
   197 /**
   198 @internalComponent
   199 */
   200 TInt CTestVirusHook::DoRequestL(TFsPluginRequest& aRequest)
   201 	{
   202 	TInt err = KErrNotSupported;
   203 
   204 	TInt function = aRequest.Function();
   205 	
   206 	iDrvNumber = aRequest.DriveNumber();
   207 
   208 	switch(function)
   209 		{
   210 		case EFsFileOpen:
   211 			err = VsFileOpen(aRequest);
   212 			break;
   213 
   214 		case EFsFileSubClose:
   215 			VsFileClose(aRequest);
   216 			break;
   217 
   218 		case EFsFileRename:
   219 		case EFsRename:
   220 		case EFsReplace:
   221 			err = VsFileRename(aRequest);
   222 			break;
   223 
   224 		case EFsDelete:
   225 			err = VsFileDelete(aRequest);
   226 			break;
   227 
   228 		case EFsReadFileSection:
   229 			err = VsReadFileSection(aRequest);
   230 			break;
   231 
   232 		default:
   233 			break;
   234 		}
   235 
   236 	return err;
   237 	}
   238 
   239 
   240 /**
   241 @internalComponent
   242 */
   243 TInt CTestVirusHook::VsFileOpen(TFsPluginRequest& aRequest)
   244 	{
   245 	TFileName fileName;
   246 	TInt err = ValidateRequest(aRequest, fileName);
   247 	if (err == KErrNone)
   248 		{
   249 		err = ScanFile(fileName);
   250 		if (err != KErrNone)
   251 			{
   252 			// Clean the infected file
   253 			CleanFile(fileName, EFileOpen);
   254 			}
   255 		}	
   256 
   257 	return err;
   258 	}
   259 
   260 /**
   261 @internalComponent
   262 */
   263 void CTestVirusHook::VsFileClose(TFsPluginRequest& aRequest)
   264 	{
   265 	TFileName fileName;
   266 	TInt err = GetName(&aRequest, fileName);
   267 	if(err == KErrNone)
   268 		{
   269 		err = ScanFile(fileName);
   270 		if (err != KErrNone)
   271 			{
   272 			// Clean the infected file
   273 			CleanFile(fileName, EFileClose);
   274 			}
   275 		}
   276 	}
   277 
   278 /**
   279 @internalComponent
   280 */
   281 TInt CTestVirusHook::VsFileRename(TFsPluginRequest& aRequest)
   282 	{
   283 
   284 	TInt err = VsDirRename(aRequest);
   285 	if(err != KErrAccessDenied)
   286 		{
   287 		TFileName fileName;
   288 		err = ValidateRequest(aRequest, fileName);
   289 		if (err == KErrNone)
   290 			{
   291 			err = ScanFile(fileName);
   292 			if (err != KErrNone)
   293 				{
   294 				// Clean the infected file
   295 				CleanFile(fileName, EFileRename);
   296 				}
   297 			}
   298 		}
   299 
   300 	return err;
   301 	}
   302 
   303 /**
   304 @internalComponent
   305 */
   306 TInt CTestVirusHook::VsDirRename(TFsPluginRequest& aRequest)
   307 	{
   308 
   309 	TFileName fileName;
   310 	TInt err = GetName(&aRequest, fileName);
   311 	if(err != KErrNone)
   312 		return(err);
   313 	
   314 	err = fileName.Find(_L("\\system\\lib\\"));
   315 	if (err != KErrNotFound)
   316 		{
   317 		//Don't allow sys\bin to be ever renamed
   318 		return KErrAccessDenied;
   319 		}
   320 	err = fileName.Find(_L("\\sys\\bin\\"));
   321 	if (err != KErrNotFound)
   322 		{
   323 		//Don't allow sys\bin to be ever renamed
   324 		return KErrAccessDenied;
   325 		}
   326 
   327 	return err;
   328 	}
   329 
   330 /**
   331 @internalComponent
   332 */
   333 TInt CTestVirusHook::VsFileDelete(TFsPluginRequest& aRequest)
   334 	{
   335 
   336 	TFileName fileName;
   337 	TInt err = ValidateRequest(aRequest, fileName);
   338 	return err;
   339 	}
   340 
   341 /**
   342 @internalComponent
   343 */
   344 TInt CTestVirusHook::VsReadFileSection(TFsPluginRequest& aRequest)
   345 	{
   346 
   347 	// The t_virus test uses a filename clean.txt, a read length of 8 and a read position of 0.
   348 	TFileName fileName;
   349 	TInt len;
   350 	TInt pos;
   351 
   352 	// test getting name on read file section intercept
   353 	TInt err = GetName(&aRequest, fileName);
   354 	if(err != KErrNone)
   355 		{
   356 		return(err);
   357 		}
   358 	TParse parse;
   359 	parse.Set(fileName,NULL,NULL);
   360 	TPtrC name = parse.Name();
   361 	if(name.CompareF(_L("clean"))!=0)
   362 		{
   363 		return(KErrGeneral);
   364 		}
   365 	TPtrC ext = parse.Ext();
   366 	if(ext.CompareF(_L(".txt"))!=0)
   367 		{
   368 		return(KErrGeneral);
   369 		}
   370 
   371 	// test getting read length and required file position on read file section intercept
   372 	err = GetFileAccessInfo(&aRequest, len, pos);
   373 	if(err != KErrNone)
   374 		{
   375 		return(err);
   376 		}
   377 	if ((len != 8) || (pos != 0))
   378 		{
   379 		return(KErrGeneral);
   380 		}
   381 	
   382 	return KErrNone;
   383 	}
   384 
   385 
   386 /**
   387 @internalComponent
   388 */
   389 TInt CTestVirusHook::VirusScannerName(TDes& aName)
   390 	{
   391 	aName = KVirusScannerName;
   392 	return KErrNone;
   393 	}
   394 
   395 /**
   396 Reads the contents of the file passed in and checks
   397 whether it contains any of the specified virus
   398 signatures
   399 
   400 @return A value depending on whether a known virus is
   401 found within the file.
   402 
   403 @param aFile A CFileCB object which can be used to read the file.
   404 @internalComponent
   405 */
   406 TInt CTestVirusHook::ScanFile(const TDesC& aName)
   407 	{
   408 
   409 	TInt r    = KErrNone;
   410 	TInt pos  = 0;
   411 	TInt size = 0;
   412 
   413 	// Rename the file	
   414 	TPtrC tmpFile = _L("VS_RENAMED.VSH");
   415 	TParse parse;
   416 	parse.Set(aName, NULL, NULL);
   417 	parse.Set(parse.DriveAndPath(), &tmpFile, NULL);
   418 
   419 	r = iFs.Rename(aName, parse.FullName());
   420 	if(r != KErrNone)
   421 		return r;
   422 
   423 	RFile file;
   424 	r = file.Open(iFs, parse.FullName(), EFileRead);
   425 	if(r == KErrNone)
   426 		{
   427 		r = file.Size(size);
   428 		}
   429 
   430 	//If the file size is 0, then the file
   431 	//has just been created - so it can't contain
   432 	//a virus.
   433 	if(r != KErrNone || size == 0)
   434 		{
   435 		file.Close();
   436 
   437 		// Rename the file back
   438 		TInt err = iFs.Rename(parse.FullName(), aName);
   439 		if(err != KErrNone)
   440 			return err;
   441 
   442 		return r;
   443 		}
   444 
   445 	do
   446 		{
   447 		r = file.Read(pos, iScanBuf);
   448 		
   449 		if (r != KErrNone)
   450 			{
   451 			break;
   452 			}
   453 
   454 		r = ScanBuffer();
   455 		pos += iScanBuf.Length();
   456 		} while ((r == KErrNotFound) && (iScanBuf.Length() == iScanBuf.MaxLength()));
   457 
   458 	file.Close();
   459 
   460 	// Rename the file back
   461 	TInt err = iFs.Rename(parse.FullName(), aName);
   462 	if(err != KErrNone)
   463 		return err;
   464 
   465 	if (r > 0)
   466 		{
   467 		//We've found an infection
   468 		return KErrAccessDenied;
   469 		}
   470 	else
   471 		{
   472 		return KErrNone;
   473 		}
   474 	}
   475 
   476 /**
   477 Scans the internal buffer which has been loaded with fresh
   478 file contents, to see if it contains any known virus
   479 signatures.
   480 
   481 @return A value depending on whether a known virus signature
   482 is found within the buffer.
   483 
   484 @internalComponent
   485 */
   486 TInt CTestVirusHook::ScanBuffer()
   487 	{
   488 	//Look through the internal buffer for all known virus signatures.
   489 
   490 	TInt r;
   491 	for (TInt i = 0; i < iSignaturesLoaded; i++)
   492 		{
   493 		r = iScanBuf.Find(iKnownSignatures[i]->Des());
   494 
   495 		if (r != KErrNotFound)
   496 			{
   497 			return r;
   498 			}
   499 		}
   500 	return KErrNone;
   501 	}
   502 
   503 /**
   504 Validate that nobody is trying to touch the virus scanner files.
   505 
   506 @internalComponent
   507 
   508 @return A value depending on whethe the virus scanner files are
   509 being fiddled with.
   510 
   511 @param aDriveNum The drive number of the request which called into
   512 the test virus scanning hook.
   513 
   514 @param aName The full pathname of the file being accessed by the
   515 request to the file server hook.
   516 */
   517 TInt CTestVirusHook::ValidateRequest(TFsPluginRequest& aRequest, TFileName& aFileName)
   518 	{
   519 	TInt driveNumber = aRequest.DriveNumber();
   520 	
   521 	TInt err = GetName(&aRequest, aFileName);
   522 	if(err != KErrNone)
   523 		return(err);
   524 	
   525 	if (driveNumber == EDriveC)
   526 		{
   527 		TInt r = aFileName.Find(_L("\\virusdef.txt"));
   528 
   529 		if (r != KErrNotFound)
   530 			{
   531 			//Do not allow the deletion of the virus definition file.
   532 			return KErrAccessDenied;
   533 			}
   534 
   535 		r = aFileName.Find(_L("\\system\\libs\\t_vshook.pxt"));
   536 		if (r != KErrNotFound)
   537 			{
   538 			//Do not allow the deletion of the this dll
   539 			return KErrAccessDenied;
   540 			}
   541 		r = aFileName.Find(_L("\\sys\\bin\\t_vshook.pxt"));
   542 		if (r != KErrNotFound)
   543 			{
   544 			//Do not allow the deletion of the this dll
   545 			return KErrAccessDenied;
   546 			}
   547 		}
   548 	return KErrNone;
   549 	}
   550 
   551 /**
   552 Processes a message which describes the detection of an
   553 infected file.  Appends the relevant text at the end of the
   554 file to say that it has been "cleaned".  This allows the virus
   555 test program to confirm that the test virus scanner is 
   556 behaving as expected.
   557 
   558 @internalComponent
   559 @param aMessage The message to be processed.
   560 */
   561 void CTestVirusHook::CleanFile(const TDesC& aName, TInt aOperation)
   562 	{
   563 	
   564 	RFile infectedFile;
   565 	TBool bChangedToRw=EFalse;
   566 	TInt pos=0;
   567 
   568 	TUint fileAtt;
   569 	TInt r = iFs.Att(aName, fileAtt);
   570 	if (r != KErrNone)
   571 		{
   572 		return;
   573 		}
   574 
   575 	if (fileAtt & KEntryAttReadOnly)
   576 		{
   577 		bChangedToRw = ETrue;
   578 		r = iFs.SetAtt(aName, 0, KEntryAttReadOnly);
   579 		}
   580 
   581 	r = infectedFile.Open(iFs, aName, EFileShareAny | EFileWrite);
   582 
   583 	if (r != KErrNone)
   584 		{
   585 		return;
   586 		}
   587 
   588 	//To show we've fixed the file, append "Infection deleted" to the end of it.
   589 	infectedFile.Seek(ESeekEnd, pos);
   590 	switch (aOperation)
   591 		{
   592 	case EFileOpen:
   593 		infectedFile.Write(_L8("infection detected - file open\\n"));
   594 		break;
   595 	case EFileDelete:
   596 		infectedFile.Write(_L8("infection detected - file delete\\n"));
   597 		break;
   598 	case EFileRename:
   599 		infectedFile.Write(_L8("infection detected - file rename\\n"));
   600 		break;
   601 	case EFileClose:
   602 		infectedFile.Write(_L8("infection detected - file close\\n"));
   603 		break;
   604 		}
   605 
   606 	infectedFile.Close();
   607 
   608 	if (bChangedToRw)
   609 		{
   610 		iFs.SetAtt(aName, KEntryAttReadOnly,0);
   611 		}
   612 	}
   613 
   614 //factory functions
   615 
   616 class CVsHookFactory : public CFsPluginFactory
   617 	{
   618 public:
   619 	CVsHookFactory();
   620 	virtual TInt Install();			
   621 	virtual CFsPlugin* NewPluginL();
   622 	virtual CFsPlugin* NewPluginConnL();
   623 	virtual TInt UniquePosition();
   624 	};
   625 
   626 /**
   627 Constructor for the plugin factory
   628 @internalComponent
   629 */
   630 CVsHookFactory::CVsHookFactory()
   631 	{
   632 	}
   633 
   634 /**
   635 Install function for the plugin factory
   636 @internalComponent
   637 */
   638 TInt CVsHookFactory::Install()
   639 	{
   640 	iSupportedDrives = KPluginAutoAttach;
   641 
   642 	_LIT(KVsHookName,"VsHook");
   643 	return(SetName(&KVsHookName));
   644 	}
   645 
   646 /**
   647 @internalComponent
   648 */
   649 TInt CVsHookFactory::UniquePosition()
   650 	{
   651 	return(0x3EC);
   652 	}
   653 
   654 /**
   655 Plugin factory function
   656 @internalComponent
   657 */
   658 CFsPlugin* CVsHookFactory::NewPluginL()
   659 
   660 	{
   661 	return CTestVirusHook::NewL();
   662 	}
   663 
   664 /**
   665 Plugin factory function
   666 @internalComponent
   667 */
   668 CFsPlugin* CVsHookFactory::NewPluginConnL()
   669 
   670 	{
   671 	return CTestVirusHook::NewL();
   672 	}
   673 
   674 /**
   675 Create a new Plugin
   676 @internalComponent
   677 */
   678 extern "C" {
   679 
   680 EXPORT_C CFsPluginFactory* CreateFileSystem()
   681 	{
   682 	return(new CVsHookFactory());
   683 	}
   684 }
   685