// Copyright (c) 2001-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:
// e32test\secure\t_platsecconfig.cpp
// This test checks the correct functioning of the Platform Security configuration.
// To use this test for verification of the features, perform the following steps
// On the WINS Emulator
// 1. Run "T_PLATSECCONFIG.EXE"
// Check that the results reported are:
// PlatSecEnforcement is OFF
// Disabled Capabilites: NONE
// Check EPOCWIND.OUT and verify that it contains no diagnostic messages. (These will start with the text "*PlatSec* ")
// 2. Run "T_PLATSECCONFIG.EXE -mt_platsecconfig --"
// Check that the results reported are:
// PlatSecEnforcement is ON
// Disabled Capabilites: CommDD MultimediaDD WriteDeviceData TrustedUI DiskAdmin AllFiles NetworkServices ReadUserData Location (These are all ODD numbered capabilities)
// Check EPOCWIND.OUT and verify that it contains two lines starting with "*PlatSec* ERROR - Capability check failed"
// On reference hardware
// 3. Build a Text Shell ROM contining the E32 tests. E.g.
// cd \cedar\generic\base\e32\rombuild
// rom -v=lubbock -t=e32test
// Boot this ROM and run "T_PLATSECCONFIG.EXE"
// Check that the results reported are:
// PlatSecEnforcement is OFF
// Disabled Capabilites: NONE
// Check the output of the debug port and verify that it contains no diagnostic messages.
// (These will start with the text "*PlatSec* ")
// 4. Build a Text Shell ROM using the T_PLATSECCONFIG.OBY file. E.g.
// cd \cedar\generic\base\e32\rombuild
// rom -v=lubbock -t=t_platsecconfig
// Boot this ROM and run "T_PLATSECCONFIG.EXE"
// Check that the results reported are:
// PlatSecEnforcement is ON
// Disabled Capabilites: CommDD MultimediaDD WriteDeviceData TrustedUI DiskAdmin AllFiles NetworkServices ReadUserData Location (These are all ODD numbered capabilities)
// Check the output of the debug port and verify that it contains two lines with "*PlatSec* ERROR - Capability check failed"
// To check ROMBUILD configuration
// 5. Build a Text Shell ROM using the T_PLATSECCONFIG_WARNIG.OBY file. E.g.
// cd \cedar\generic\base\e32\rombuild
// rom -v=lubbock -t=t_platsecconfig_warning
// This should produce the following warning:
// WARNING: *PlatSec* WARNING - Capability check failed. Can't load \Epoc32\RELEASE\ARM4\UDEB\t_psc_static.exebecause it links to t_psc_dll{00010000}.dll which has the following capabilities missing: TCB PowerMgmt ReadDeviceData DRM ProtServ NetworkControl SwEvent LocalServices WriteUserData
// 6. Build a Text Shell ROM using the T_PLATSECCONFIG_ERROR.OBY file. E.g.
// cd \cedar\generic\base\e32\rombuild
// rom -v=lubbock -t=t_platsecconfig_error
// This should produce the following error:
// ERROR: *PlatSec* ERROR - Capability check failed. Can't load \Epoc32\RELEASE\ARM4\UDEB\t_psc_static.exe because it links to t_psc_dll{00010000}.dll which has the following capabilities missing: TCB PowerMgmt ReadDeviceData DRM ProtServ NetworkControl SwEvent LocalServices WriteUserData
//
//
/**
@file
*/
#define __INCLUDE_CAPABILITY_NAMES__
#include <e32test.h>
LOCAL_D RTest test(_L("T_PLATSECCONFIG"));
enum TTestProcessFunctions
{
ETestProcessServer,
ETestProcessLoadLib,
};
#include "testprocess.h"
TInt StartServer();
TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
{
(void)aArg1;
(void)aArg2;
switch(aTestNum)
{
case ETestProcessServer:
return StartServer();
case ETestProcessLoadLib:
{
RLibrary lib;
TInt r = lib.Load(_L("T_PSC_DLL"));
lib.Close();
return r;
}
default:
User::Panic(_L("T_PLATSECCONFIG"),1);
}
return KErrNone;
}
//
// RTestThread
//
class RTestThread : public RThread
{
public:
void Create(TThreadFunction aFunction,TAny* aArg=0);
};
void RTestThread::Create(TThreadFunction aFunction,TAny* aArg)
{
TInt r=RThread::Create(_L(""),aFunction,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,aArg);
test(r==KErrNone);
}
//
// CTestSession
//
class CTestSession : public CSession2
{
public:
enum {EShutdown,EGetSecurityInfo};
public:
CTestSession();
virtual void ServiceL(const RMessage2& aMessage);
public:
};
CTestSession::CTestSession()
: CSession2()
{}
void CTestSession::ServiceL(const RMessage2& aMessage)
{
RMessagePtr2 m(aMessage);
switch (aMessage.Function())
{
case CTestSession::EGetSecurityInfo:
{
TSecurityInfo info;
info.Set(RProcess());
TInt r = aMessage.Write(0,TPtrC8((TUint8*)&info,sizeof(info)));
m.Complete(r);
}
break;
case CTestSession::EShutdown:
CActiveScheduler::Stop();
break;
default:
m.Complete(KErrNotSupported);
break;
}
}
//
// CTestServer
//
class CTestServer : public CServer2
{
public:
CTestServer(TInt aPriority);
virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
};
CTestServer::CTestServer(TInt aPriority)
: CServer2(aPriority)
{
}
CSession2* CTestServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const
{
return new (ELeave) CTestSession();
}
//
// CTestActiveScheduler
//
class CTestActiveScheduler : public CActiveScheduler
{
public:
virtual void Error(TInt anError) const;
};
void CTestActiveScheduler::Error(TInt anError) const
{
User::Panic(_L("TestServer Error"),anError);
}
//
// Server thread
//
_LIT(KServerName,"T_PLATSECCONFIG-server");
const TInt KServerRendezvous = KRequestPending+1;
void DoStartServer()
{
CTestActiveScheduler* activeScheduler = new (ELeave) CTestActiveScheduler;
CActiveScheduler::Install(activeScheduler);
CleanupStack::PushL(activeScheduler);
CTestServer* server = new (ELeave) CTestServer(0);
CleanupStack::PushL(server);
User::LeaveIfError(server->Start(KServerName));
RProcess::Rendezvous(KServerRendezvous);
CActiveScheduler::Start();
CleanupStack::PopAndDestroy(2);
}
TInt StartServer()
{
CTrapCleanup* cleanupStack = CTrapCleanup::New();
if(!cleanupStack)
return KErrNoMemory;
TRAPD(leaveError,DoStartServer())
delete cleanupStack;
return leaveError;
}
//
// RTestSession
//
class RTestSession : public RSessionBase
{
public:
inline TInt Connect()
{ return CreateSession(KServerName,TVersion());}
inline TInt Send(TInt aFunction)
{ return RSessionBase::SendReceive(aFunction); }
inline TInt Send(TInt aFunction,const TIpcArgs& aArgs)
{ return RSessionBase::SendReceive(aFunction,aArgs); }
inline void Send(TInt aFunction,TRequestStatus& aStatus)
{ RSessionBase::SendReceive(aFunction,aStatus); }
inline void Send(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus)
{ RSessionBase::SendReceive(aFunction,aArgs,aStatus); }
};
RTestSession Session;
void CheckCapabilitySetEqual(const TCapabilitySet& a1,const TCapabilitySet& a2)
{
TInt i;
for(i=0; i<ECapability_Limit; i++)
test((!a1.HasCapability((TCapability)i))==(!a2.HasCapability((TCapability)i)));
}
TBuf8<1024> CapabilityNameBuffer;
TBool PlatSecEnforcement=0;
TPtrC16 CapabilityList(const TCapabilitySet& aCaps)
{
TCapabilitySet allCaps;
allCaps.SetAllSupported();
CapabilityNameBuffer.Zero();
TBool odd=ETrue;
TBool even=ETrue;
TInt i;
for(i=0; i<ECapability_Limit; i++)
{
if(!aCaps.HasCapability((TCapability)i))
{
if(allCaps.HasCapability((TCapability)i))
{
if(i&1)
odd = EFalse;
else
even = EFalse;
}
continue;
}
TUint8* ptr=(TUint8*)CapabilityNames[i];
TPtrC8 name(ptr,User::StringLength(ptr));
CapabilityNameBuffer.Append(name);
CapabilityNameBuffer.Append((TChar)' ');
}
if(!CapabilityNameBuffer.Length())
CapabilityNameBuffer.Append(_L8("NONE"));
if(even)
CapabilityNameBuffer.Append(_L8("(These are all EVEN numbered capabilities)"));
if(odd)
CapabilityNameBuffer.Append(_L8("(These are all ODD numbered capabilities)"));
return CapabilityNameBuffer.Expand();
}
void TestPlatSecDisabledCaps()
{
TSecurityInfo info;
TPckg<TSecurityInfo> infoPtr(info);
test.Start(_L("Get disabled capabilities set"));
TCapabilitySet disabled;
disabled.SetDisabled();
TPtrC16 list(CapabilityList(disabled));
test.Printf(_L(" %S\n"),&list);
test.Next(_L("Get capabilites from this EXE"));
Mem::FillZ(&info,sizeof(info));
info.SetToCurrentInfo();
test.Next(_L("Check capabilities are same as disabled set"));
CheckCapabilitySetEqual(info.iCaps,disabled);
test.Next(_L("Get capabilites from other EXE"));
Mem::FillZ(&info,sizeof(info));
TInt r = Session.Send(CTestSession::EGetSecurityInfo,TIpcArgs(&infoPtr));
test(r==KErrNone);
test.Next(_L("Check capabilities are same as disabled set"));
CheckCapabilitySetEqual(info.iCaps,disabled);
test.Next(_L("Test PlatSec::IsCapabilityEnforced is consistant with our findings"));
TCapabilitySet notEnforced;
notEnforced.SetEmpty();
for(TInt i=0; i<ECapability_HardLimit; i++)
if(!PlatSec::IsCapabilityEnforced((TCapability)i))
notEnforced.AddCapability((TCapability)i);
if(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement))
disabled.SetAllSupported();
CheckCapabilitySetEqual(notEnforced,disabled);
test.End();
}
_LIT(KRomExe,"T_PLATSECCONFIG2.EXE");
_LIT(KOn,"ON");
_LIT(KOff,"OFF");
void TestPlatSecEnforcement()
{
RProcess process;
TInt r;
test.Start(_L("Getting PlatSecEnforcement setting"));
PlatSecEnforcement = PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement);
test.Printf(_L(" PlatSecEnforcement setting returns %S\n"),PlatSecEnforcement?&KOn:&KOff);
test.Next(_L("Check dynamic linkage without required capabilities"));
TBuf<10> arg;
arg.Num((TInt)ETestProcessLoadLib);
r=process.Create(_L("T_PSC_DYNAMIC"),arg);
test(r==KErrNone);
TRequestStatus logon;
process.Logon(logon);
process.Resume();
User::WaitForRequest(logon);
test(process.ExitType()==EExitKill);
r=logon.Int();
CLOSE_AND_WAIT(process);
if(PlatSecEnforcement)
test(r==KErrPermissionDenied);
else
test(r==KErrNone);
test.Next(_L("Check static linkage without required capabilities"));
r=process.Create(_L("T_PSC_STATIC"),_L(""));
if(PlatSecEnforcement)
test(r==KErrPermissionDenied);
else
{
test(r==KErrNone);
process.Kill(0);
CLOSE_AND_WAIT(process);
}
test.End();
}
#include <e32svr.h>
IMPORT_C void dummyExport();
GLDEF_C TInt E32Main()
{
#ifdef STATIC_TEST_LINK
dummyExport(); // Use dummy export from staticly linked DLL
#endif
TBuf16<512> cmd;
User::CommandLine(cmd);
if(cmd.Length() && TChar(cmd[0]).IsDigit())
{
TInt function = -1;
TInt arg1 = -1;
TInt arg2 = -1;
TLex lex(cmd);
lex.Val(function);
lex.SkipSpace();
lex.Val(arg1);
lex.SkipSpace();
lex.Val(arg2);
return DoTestProcess(function,arg1,arg2);
}
test.Title();
test.Start(_L("Starting test server"));
RTestProcess server;
TRequestStatus rendezvous;
TBuf<10> arg;
arg.Num((TInt)ETestProcessServer);
TInt r=server.RProcess::Create(KRomExe,arg);
test(r==KErrNone);
server.Rendezvous(rendezvous);
server.Resume();
User::WaitForRequest(rendezvous);
test(rendezvous==KServerRendezvous);
test.Next(_L("Openning server session"));
r = Session.Connect();
RDebug::Print(_L("%d"),r);
test(r==KErrNone);
test.Next(_L("Test PlatSecDisabledCaps"));
TestPlatSecDisabledCaps();
test.Next(_L("Test PlatSecEnforcement"));
TestPlatSecEnforcement();
test.Next(_L("Closing server session"));
Session.Send(CTestSession::EShutdown);
Session.Close();
CLOSE_AND_WAIT(server);
// Show results requiring manual inspection
_LIT(KSeperatorText,"----------------------------------------------------------------------------\n");
test.Printf(_L("\n"));
test.Printf(_L("RESULTS (To be checked against expected values)\n"));
test.Printf(KSeperatorText);
test.Printf(_L("* PlatSecEnforcement is %S\n"),PlatSecEnforcement?&KOn:&KOff);
test.Printf(KSeperatorText);
TCapabilitySet disabled;
disabled.SetDisabled();
TPtrC16 list(CapabilityList(disabled));
test.Printf(_L("* Disabled Capabilites: %S\n"),&list);
test.Printf(KSeperatorText);
// Wait for a while, or for a key press
test.Printf(_L("Waiting a short while for key press...\n"));
TRequestStatus keyStat;
test.Console()->Read(keyStat);
RTimer timer;
test(timer.CreateLocal()==KErrNone);
TRequestStatus timerStat;
timer.After(timerStat,20*1000000);
User::WaitForRequest(timerStat,keyStat);
TInt key = 0;
if(keyStat!=KRequestPending)
key = test.Console()->KeyCode();
timer.Cancel();
test.Console()->ReadCancel();
User::WaitForAnyRequest();
test.End();
return(0);
}