diff -r 000000000000 -r 95b198f216e5 omadrm/drmengine/server/src/DRMRightsServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omadrm/drmengine/server/src/DRMRightsServer.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,1437 @@ +/* +* Copyright (c) 2003 - 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: DRM3 Engine manages all DRM related database operations. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#endif + +#include "DRMRightsServer.h" +#include "DRMRightsDb.h" +#include "DRMDbSession.h" +#include "DRMEngineClientServer.h" +#include "DRMLog.h" +#include "DRMNotifier.h" +#include "DrmKeyStorage.h" +#include "drmnotifierserver.h" +#include "roapstorageserver.h" +#include "drmnotifierclientserver.h" +#include "drmroapclientserver.h" +#include "DRMXOma.h" +#include "DRMBackupObserver.h" +#include "DRMBackup.h" +#include "flogger.h" +#include "drmrightsparser.h" +#include "drmrights.h" +#include "drmhelpercommon.h" + +#include "wmdrmclientwrapper.h" + + + +#ifdef __DRM_CLOCK +#include "DRMClockServer.h" +#include "drmclockclientserver.h" +#endif + +#include +#include + +/* +_LIT( KLogDir, "drm"); +_LIT( KLogName, "backup.log"); +*/ + +// EXTERNAL DATA STRUCTURES +// EXTERNAL FUNCTION PROTOTYPES +// CONSTANTS +LOCAL_C const TUint KMaxHeapsize = 0x7A120; + +_LIT8( KImsiId,"IMSI:"); + +// MACROS +#ifdef _DRM_TESTING +_LIT( KDateTimeFormat, "%F%Y%M%D%H%T%S%C" ); +#endif + +// LOCAL CONSTANTS AND MACROS +const TUint8 KMaxStartTries = 30; +const TInt KWaitingTime = 2000000; // 2 sec +_LIT( KRightsServerThread, "RightsServer" ); + +#ifdef RD_MULTIPLE_DRIVE + +_LIT( KDbTempPath, "%c:\\system\\temp\\" ); +_LIT( KIndividualConstraintExtensionDll, "%c:\\sys\\bin\\DRMIndividualConstraintExtension.dll" ); +_LIT( KRightsDir, "%c:\\private\\101F51F2\\rdb\\" ); +_LIT( KTimedReplayCacheFile, "%c:\\private\\101F51F2\\timererc.dat" ); +_LIT( KPlainReplayCacheFile, "%c:\\private\\101F51F2\\plainrc.dat" ); +#ifdef RD_DRM_METERING +_LIT( KMeteringDataBaseFile, "%c:\\private\\101F51F2\\meterdb.dat" ); +#endif + +#define USE_RO_IMPORT + +#ifdef USE_RO_IMPORT +_LIT( KInternalImportDir, "%c:\\private\\101F51F2\\import\\" ); +_LIT( KUserDiskImportDir, "%c:\\import\\" ); // usually embedded MMC +_LIT( KUserRemovableDiskImportDir, "%c:\\import\\" ); // usually external MMC +_LIT( KDrSuffix, ".dr" ); +#endif + +#else + +_LIT( KRightsDir, "c:\\private\\101F51F2\\rdb\\" ); +_LIT( KTimedReplayCacheFile, "c:\\private\\101F51F2\\timererc.dat" ); +_LIT( KPlainReplayCacheFile, "c:\\private\\101F51F2\\plainrc.dat" ); +#ifdef RD_DRM_METERING +_LIT( KMeteringDataBaseFile, "c:\\private\\101F51F2\\meterdb.dat" ); +#endif + +#define USE_RO_IMPORT + +#ifdef USE_RO_IMPORT +_LIT( KInternalImportDir, "c:\\private\\101F51F2\\import\\" ); +_LIT( KUserDiskImportDir, "e:\\import\\" ); +_LIT( KDrSuffix, ".dr" ); +#endif + +#endif + +_LIT(KWmDrmClientWrapperName, "wmdrmclientwrapper.dll"); + +// MODULE DATA STRUCTURES + +NONSHARABLE_STRUCT( TUnloadModule ) + { + RTelServer* iServer; + const TDesC* iName; + }; + +// LOCAL FUNCTION PROTOTYPES + +LOCAL_C TInt Startup( void ); +LOCAL_C void SignalClient(); +LOCAL_C TInt StartDBServer( void ); + +#if defined( __WINS__ ) +#else +#define DRM_USE_SERIALNUMBER_URI +#include +#endif + + +#ifdef DRM_USE_SERIALNUMBER_URI +LOCAL_C void DoUnloadPhoneModule( TAny* aAny ); +#endif + +// #define USE_RO_IMPORT + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== +// ----------------------------------------------------------------------------- +// Function Startup(). +// This function starts the actual DRM Rights server after initializing +// the cleanup stack and active scheduler. +// Returns: TInt: Symbian OS error code. +// ----------------------------------------------------------------------------- +// +LOCAL_C TInt Startup( void ) + { + TInt error = KErrNone; + CTrapCleanup* trap = CTrapCleanup::New(); + CActiveScheduler* scheduler = new CActiveScheduler(); + + if ( trap && scheduler ) + { + CActiveScheduler::Install( scheduler ); + + error = StartDBServer(); + } + else + { + error = KErrNoMemory; + } + + delete scheduler; + scheduler = NULL; + + delete trap; + trap = NULL; + + if ( error ) + { + // Something went wrong. Release the client (if any). + SignalClient(); + + if ( error == KErrAlreadyExists ) + { + error = KErrNone; + } + } + + return error; + } + +// ----------------------------------------------------------------------------- +// Function SignalClient(). +// Signal the waiting client (one of them if any exists). +// ----------------------------------------------------------------------------- +// +void SignalClient( void ) + { + RSemaphore semaphore; + if ( !semaphore.OpenGlobal( DRMEngine::KDRMSemaphore ) ) + { + semaphore.Signal(); + semaphore.Close(); + } + } + +// ----------------------------------------------------------------------------- +// Function StartDBServer(). +// This function starts the actual server under TRAP harness and starts +// waiting for connections. This function returns only if there has been +// errors during server startup or the server is stopped for some reason. +// +// Returns: TInt: Symbian OS error code. +// ----------------------------------------------------------------------------- +TInt StartDBServer( void ) + { + TInt error = KErrNone; + CDRMRightsServer* server = NULL; + TUint8 count = 0; + + do + { + DRMLOG2( _L( "RightsServer.exe: StartDBServer: %d" ), error ); + + ++count; + + TRAP( error, ( server = CDRMRightsServer::NewL() ) ); + + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32(KWaitingTime) ); + } + + } while( error && ( count <= KMaxStartTries ) ); + + if( error ) + { + DRMLOG2( _L( "RightsServer.exe: CDRMRightsServer::NewL failed: %d " ), error ); + // Failed + return error; + } + + // Release the semaphore if necessary. + SignalClient(); + + // Start waiting for connections + CActiveScheduler::Start(); + + // Dying... + // Delete CDRMRigntsServer + + DRMLOG( _L( "RightsServer.exe: DB server dying..." ) ); + + delete server; + + return KErrNone; + } + +#ifdef DRM_USE_SERIALNUMBER_URI +// ----------------------------------------------------------------------------- +// Function DoUnloadPhoneModule +// Unload phone module +// ----------------------------------------------------------------------------- +// +void DoUnloadPhoneModule( TAny* aAny ) + { + __ASSERT_DEBUG( aAny, User::Invariant() ); + TUnloadModule* module = ( TUnloadModule* ) aAny; + module->iServer->UnloadPhoneModule( *( module->iName ) ); + } +#endif + +#ifdef USE_RO_IMPORT +// ----------------------------------------------------------------------------- +// PointerArrayResetDestroyAndClose +// Template method used to push RPointerArrays to the cleanup stack. Takes +// care of deleting all pointers in the array. +// ----------------------------------------------------------------------------- +// +template +void PointerArrayResetDestroyAndClose(TAny* aPtr) + { + (reinterpret_cast*>(aPtr))->ResetAndDestroy(); + (reinterpret_cast*>(aPtr))->Close(); + } +#endif + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CDRMRightsServer* CDRMRightsServer::NewL() + { + CDRMRightsServer* self = new( ELeave ) CDRMRightsServer(); + + CleanupStack::PushL( self ); + + self->ConstructL(); + + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +CDRMRightsServer::~CDRMRightsServer() + { + DRMLOG( _L( "CDRMRightsServer::~" ) ); + + delete iIMEI; iIMEI = NULL; + + delete iIMSI; iIMSI = NULL; + + delete iDb; iDb = NULL; + + iClock.Close(); + iCache.Close(); + + iMeteringDb.Close(); + + iFs.Close(); + iActiveCountConstraints.ResetAndDestroy(); + iActiveCountConstraints.Close(); + + delete iBackupObserver; + delete iBackupHandler; + delete iActiveBackupClient; + delete iDbWatcher; + +#if 0 + // Close and delete the shared data client + if( iSharedDataClient ) + { + iSharedDataClient->Close(); + delete iSharedDataClient; + iSharedDataClient = NULL; + } +#endif + + if( iNotifier ) + { + delete iNotifier; iNotifier = NULL; + } + + //An empty semaphore + RSemaphore semaphore; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetSecureTime +// Fetch the time from (secure) source. +// ----------------------------------------------------------------------------- +// +TBool CDRMRightsServer::GetSecureTime( TTime& aTime ) const + { + DRMClock::ESecurityLevel secLevel = DRMClock::KInsecure; + + TInt timezone( 0 ); + + iClock.GetSecureTime( aTime, timezone, secLevel ); + + if( secLevel == DRMClock::KSecure ) + { + DRMLOG( _L( "CDRMRightsServer::GetSecureTime: Time is secure\r\n" ) ); + return ETrue; + } + + DRMLOG( _L( "CDRMRightsServer::GetSecureTime: Time is not secure\r\n" ) ); + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::Notifier +// Return a handle to DRM Notifier. +// ----------------------------------------------------------------------------- +// +CDRMNotifier& CDRMRightsServer::Notifier() + { + return *iNotifier; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::Notifier +// Return a handle to DRM Notifier. +// ----------------------------------------------------------------------------- +// +CDRMRightsDB& CDRMRightsServer::Database() + { + return *iDb; + } + +RFs& CDRMRightsServer::FileServerSession() + { + return iFs; + } + + +RDRMReplayCache& CDRMRightsServer::ReplayCache() + { + return iCache; + } + + +RDrmMeteringDb& CDRMRightsServer::MeteringDatabase() + { + return iMeteringDb; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::HandleNotifyL +// Forward the event to the database. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::HandleNotifyL(const TUid /*aUid*/, + const TDesC& /*aKey*/, + const TDesC& /*aValue*/) + { + /* XXX Backup via Publish/Subscribe + __ASSERT_DEBUG( iDb, User::Invariant() ); + TInt value = -1; + TLex16 parser( aValue ); + + if ( aUid == KSDUidSystem ) + { + // Check if it's a backup / restore status event + if( !aKey.Compare( KBackupRestoreStatus ) ) + { + User::LeaveIfError( parser.Val( value ) ); + if( value == 3 ) // Complete + { + iDb->MergeDBL(); + } + } + // Check if it's a drm backup restore status event + else if ( aUid == KSDUidSystem ) + { + if( !aKey.Compare( KDRMBackupRestoreStatus ) ) + { + User::LeaveIfError( parser.Val( value ) ); + + if( value == 1 ) // PrepareForBackup + { + TRAPD( error, iDb->BackupDBL( KNullDesC, + KNullDesC8 ) ); + // Notify that it's done + User::LeaveIfError( iSharedDataClient->AssignToTemporaryFile( + KSDUidSystem ) ); + User::LeaveIfError( iSharedDataClient->SetInt( + KDRMBackupRestoreStatus, 0 ) ); + iSharedDataClient->Flush(); + } + } + } + } + */ + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::RunErrorL +// From CActive. Complete the request and restart the scheduler. +// ----------------------------------------------------------------------------- +// +TInt CDRMRightsServer::RunError( TInt aError ) + { + DRMLOG2( _L( "CDRMRightsServer::RunError: %d" ), aError ); + + // Inform the client. + if ( !Message().IsNull() ) + { + Message().Complete( aError ); + } + + // Restart the scheduler. + ReStart(); + + // Error handled. + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::NewSessionL +// Called when a client requires a new instance. +// ----------------------------------------------------------------------------- +CSession2* CDRMRightsServer::NewSessionL( const TVersion& aVersion, + const RMessage2& /*aMessage*/ ) const + { + DRMLOG( _L( "CDRMRightsServer::NewSessionL" ) ); + + if ( ! User::QueryVersionSupported( TVersion( DRMEngine::KServerMajorVersion, + DRMEngine::KServerMinorVersion, + DRMEngine::KServerBuildVersion ), + aVersion ) ) + { + // Sorry, no can do. + User::Leave( KErrNotSupported ); + } + + DRMLOG( _L( "CDRMRightsServer::NewSessionL: Creating a new session" ) ); + + return CDRMDbSession::NewL(); + } +// ----------------------------------------------------------------------------- +// CDRMRightsServer::CDRMRightsServer +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CDRMRightsServer::CDRMRightsServer() : + CServer2( EPriorityStandard ), + iIMEI( NULL ), + iArmed( EFalse ), + iIMSI( NULL ), + iGetImsi( ETrue ) + { + // Nothing + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::ConstructL() + { + DRMLOG( _L( "CDRMRightsServer::ConstructL" ) ); + + TDRMKey key; + RSemaphore semaphore; + RProcess currentprocess; + + // Ignore errors + User::RenameThread( KRightsServerThread ); + User::LeaveIfError( iFs.Connect() ); + +#ifndef RD_MULTIPLE_DRIVE + + // Ignore errors + iFs.MkDirAll( KDRMDbTempPath ); + +#else //RD_MULTIPLE_DRIVE + + TFileName tempPath; + TFileName tempPath2; + TFileName tempRemovablePath; + TInt driveNumber( -1 ); + TChar driveLetter; + TChar driveLetterRemovable; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KDbTempPath, (TUint)driveLetter ); + + // Ignore errors + iFs.MkDirAll( tempPath ); + +#endif + + DRMLOG( _L( "CDRMRightsServer::ConstructL: SharedDataClient" ) ); + + // Create and instance of the shared data client + // iSharedDataClient = new (ELeave) RSharedDataClient(this); + + // Connecting to the shared data server + // User::LeaveIfError(iSharedDataClient->Connect()); + + /* XXX Backup via Publish/Subscribe + User::LeaveIfError(iSharedDataClient->NotifyChange( + KSDUidSystem, &KBackupRestoreStatus ) ); + User::LeaveIfError(iSharedDataClient->NotifyChange( + KSDUidSystem, &KDRMBackupRestoreStatus) ); + */ + + + GetDbKeyL( key ); + + + DRMLOG( _L( "CDRMRightsServer::ConstructL: database" ) ); + + GetIMEIL(); + + // Create the imsi pointer array: + iIMSI = CDRMPointerArray::NewL(); + iIMSI->SetAutoCleanup(ETrue); + + GetIMSIL(); + +#ifndef RD_MULTIPLE_DRIVE + + iDb = CDRMRightsDB::NewL( iFs, KRightsDir, key, *iIMEI ); + +#else //RD_MULTIPLE_DRIVE + + tempPath.Format( KRightsDir, (TUint)driveLetter ); + + iDb = CDRMRightsDB::NewL( iFs, tempPath, key, *iIMEI ); + +#endif + + key.FillZ(); + + DRMLOG( _L( "CDRMRightsServer::ConstructL: DB started." ) ); + + DRMLOG( _L( "CDRMRightsServer::ConstructL: Starting Notifier ." ) ); + + User::LeaveIfError( semaphore.CreateGlobal( KDRMEngCommonSemaphore, 0 ) ); + CleanupClosePushL( semaphore ); + + StartThreadL( DRMNotifier::KServerName, StartupNotifier, semaphore ); + DRMLOG( _L( "CDRMRightsServer::ConstructL: Notifier thread created." ) ); + + StartThreadL( Roap::KServerName, StartupRoapStorage, semaphore ); + DRMLOG( _L( "CDRMRightsServer::ConstructL: ROAP thread created." ) ); + +#ifdef __DRM_CLOCK + StartThreadL( DRMClock::KServerName, StartupClock, semaphore ); + DRMLOG( _L( "CDRMRightsServer::ConstructL: clock thread created." ) ); +#endif + + CleanupStack::PopAndDestroy(); // semaphore + + iNotifier = CDRMNotifier::NewL(); + + iCache.Set( iFs ); + +#ifndef RD_MULTIPLE_DRIVE + + iCache.InitL( KTimedReplayCacheFile, KPlainReplayCacheFile ); + +#ifdef RD_DRM_METERING + iMeteringDb.Set( iFs ); + iMeteringDb.InitL( KMeteringDataBaseFile ); +#endif + +#else //RD_MULTIPLE_DRIVE + + tempPath.Format( KTimedReplayCacheFile, (TUint)driveLetter ); + tempPath2.Format( KPlainReplayCacheFile, (TUint)driveLetter ); + + iCache.InitL( tempPath, tempPath2 ); + +#ifdef RD_DRM_METERING + + tempPath.Format( KMeteringDataBaseFile, (TUint)driveLetter ); + + iMeteringDb.Set( iFs ); + iMeteringDb.InitL( tempPath ); + +#endif + +#endif + + User::LeaveIfError( iClock.Connect() ); + + // xoma header list creation + iXOmaHeaders = new (ELeave) RPointerArray< CDRMXOma >(); + + // p/s + iBackupObserver = CDRMBackupObserver::NewL( *(const_cast(this))); + iBackupObserver->Start(); + +#ifdef USE_RO_IMPORT + // Import any OMA DRM 1.0 RO in the import directory, ignore all errors (except + // when checking the default removable mass storage) + TInt r = KErrNone; + +#ifndef RD_MULTIPLE_DRIVE + + TRAP( r, ImportRightsObjectsL( KInternalImportDir ) ); + TRAP( r, ImportRightsObjectsL( KUserDiskImportDir ) ); + +#else //RD_MULTIPLE_DRIVE + + tempPath.Format( KInternalImportDir, (TUint)driveLetter ); + + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + // Default mass storage is usually eMMC + tempPath2.Format( KUserDiskImportDir, (TUint)driveLetter ); + + // Find out if a removable mass storage also exists + r = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRemovableMassStorage, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetterRemovable ); + + // Import is not needed from the default removable mass storage drive if the drive + // letter of the default mass storage and the default removable mass storage are + // the same or the removable mass storage is not supported + if ( ( driveLetter != driveLetterRemovable ) && ( r == KErrNone ) ) + { + tempRemovablePath.Format( KUserRemovableDiskImportDir, (TUint)driveLetterRemovable ); + TRAP( r, ImportRightsObjectsL( tempRemovablePath ) ); + } + + TRAP( r, ImportRightsObjectsL( tempPath ) ); + TRAP( r, ImportRightsObjectsL( tempPath2 ) ); + +#endif + +#endif + + // Add the server to the scheduler. + StartL( DRMEngine::KServerName ); + + // Start watching our RDB + iDbWatcher = CDbWatcher::NewL( *this ); + iDbWatcher->StartWatching(); + + // Start watching the helper server + iProcWatcher = CProcWatcher::NewL( *this, _L( "*DcfRepSrv*" ), _L( "DcfRepSrv" ) ); + iProcWatcher->StartWatching(); + + // Ready to watch + iArmed = ETrue; + + __UHEAP_MARK; + TRAP( r, FeatureManager::InitializeLibL() ); + if( !r && FeatureManager::FeatureSupported( KFeatureIdWindowsMediaDrm ) ) + { + static const TInt KGateOrdinal = 1; + RLibrary library; + r = library.Load( KWmDrmClientWrapperName ); + if( !r ) + { + CWmDrmClientWrapper* wrapper = NULL; + TLibraryFunction function = library.Lookup( KGateOrdinal ); + if( function != NULL ) + { + __UHEAP_MARK; + TRAP( r, wrapper = reinterpret_cast( function() ) ); + if( !r ) + { + r = wrapper->Connect(); + } + delete wrapper; + __UHEAP_MARKEND; + } + } + library.Close(); + } + FeatureManager::UnInitializeLib(); + __UHEAP_MARKEND; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::StartThreadL +// Start a new thread. +// ----------------------------------------------------------------------------- +void CDRMRightsServer::StartThreadL( const TDesC& aThreadName, + TThreadFunction aFunc, + RSemaphore& aSemaphore ) + { + RThread thread; + + User::LeaveIfError( + thread.Create( aThreadName, + aFunc, + KDefaultStackSize, + KMinHeapSize, + KMaxHeapsize, + NULL ) ); + + thread.Resume(); + + aSemaphore.Wait(); + + thread.Close(); + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetDbKeyL +// Fetches the rights database key from Wallet or uses a constant +// key if Wallet is not supported. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::GetDbKeyL( TDRMKey& aKey ) + { + TInt r = KErrNone; + + DRMLOG( _L( "CDRMRightsServer::GetDbKey" ) ); + MDrmKeyStorage* storage = DrmKeyStorageNewL(); + TRAP( r, storage->GetDeviceSpecificKeyL( aKey ) ); + delete storage; + User::LeaveIfError( r ); + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GenerateKeyL +// Generates the actual key based on the given key seed. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::GenerateKeyL( HBufC*& aKeySeed, + TDRMKey& aKey ) const + { + __ASSERT_ALWAYS( aKeySeed->Size() >= KDRMKeyLength, + User::Leave( KErrUnderflow ) ); + + TPtrC8 key( reinterpret_cast< TUint8* >( const_cast< TUint16* >( aKeySeed->Ptr() ) ), + KDRMKeyLength ); + + aKey = key; + } + + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::XOmaHeaders() +// return the pointer of the X-Oma headers list +// ----------------------------------------------------------------------------- +// +RPointerArray< CDRMXOma >& CDRMRightsServer::XOmaHeaders( void ) + { + return *iXOmaHeaders; + } + + + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetIMEIL +// ----------------------------------------------------------------------------- +// +const TDesC& CDRMRightsServer::GetIMEIL() + { + if ( iIMEI ) + { + return *iIMEI; + } + +#ifdef DRM_USE_SERIALNUMBER_URI + TInt error( KErrNone ); + TInt count( 0 ); + TInt count2( 0 ); + TUint32 caps( 0 ); + TBool found (EFalse); + + RTelServer etelServer; + RMobilePhone phone; + + TUint KMaxImeiTries = 5; + + for ( TUint8 i = 0; i < KMaxImeiTries; ++i ) + { + error = etelServer.Connect(); + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) ); + } + else + { + break; + } + } + + User::LeaveIfError( error ); + CleanupClosePushL( etelServer ); + + User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); + + TUnloadModule unload; + unload.iServer = &etelServer; + unload.iName = &KMmTsyModuleName; + + TCleanupItem item( DoUnloadPhoneModule, &unload ); + CleanupStack::PushL( item ); + User::LeaveIfError( etelServer.EnumeratePhones( count ) ); + + for ( count2 = 0; count2 < count && !found; ++count2 ) + { + RTelServer::TPhoneInfo phoneInfo; + User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) ); + + if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 ) + { + User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) ); + User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); + CleanupClosePushL( phone ); + found = ETrue; + } + } + + if ( !found ) + { + // Not found. + User::Leave( KErrNotFound ); + } + + User::LeaveIfError( phone.GetIdentityCaps( caps ) ); + if ( caps & RMobilePhone::KCapsGetSerialNumber ) + { + RMobilePhone::TMobilePhoneIdentityV1 id; + TRequestStatus status; + + phone.GetPhoneId( status, id ); + + User::WaitForRequest( status ); + + User::LeaveIfError( status.Int() ); + + iIMEI = id.iSerialNumber.AllocL(); + + CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer + + HBufC8* buf = HBufC8::NewL( iIMEI->Size() ); + TPtr8 ptr( buf->Des() ); + ptr.Copy( *iIMEI ); + + DRMLOG(_L("IMEI:")); + DRMLOGHEX(ptr); + delete buf; + + return *iIMEI; + } + + User::Leave( KErrNotFound ); + + // Never happens... + return *iIMEI; + +#else + _LIT( KDefaultSerialNumber, "123456789123456789" ); + iIMEI = KDefaultSerialNumber().AllocL(); + + return *iIMEI; +#endif + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetIMSIL +// ----------------------------------------------------------------------------- +// +const CDRMPointerArray& CDRMRightsServer::GetIMSIL() + { + + if ( !iGetImsi ) + { + return *iIMSI; + } + +#ifndef __WINS__ + TInt error( KErrNone ); + TInt count( 0 ); + TInt count2( 0 ); + TUint32 caps( 0 ); + TBool found (EFalse); + HBufC8* imsi = NULL; + HBufC8* imsiNumber = NULL; + + RTelServer etelServer; + RMobilePhone phone; + + TUint KMaxImeiTries = 5; + for ( TUint8 i = 0; i < KMaxImeiTries; ++i ) + { + error = etelServer.Connect(); + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) ); + } + else + { + break; + } + } + + User::LeaveIfError( error ); + CleanupClosePushL( etelServer ); + User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); + + TUnloadModule unload; + unload.iServer = &etelServer; + unload.iName = &KMmTsyModuleName; + + TCleanupItem item( DoUnloadPhoneModule, &unload ); + CleanupStack::PushL( item ); + + User::LeaveIfError( etelServer.EnumeratePhones( count ) ); + + for ( count2 = 0; count2 < count && !found; ++count2 ) + { + RTelServer::TPhoneInfo phoneInfo; + User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) ); + + if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 ) + { + User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) ); + User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); + CleanupClosePushL( phone ); + found = ETrue; + } + } + + if ( !found ) + { + // Not found. + User::Leave( KErrNotFound ); + } + + + User::LeaveIfError( phone.GetIdentityCaps( caps ) ); + + if( caps & RMobilePhone::KCapsGetSubscriberId ) + { + RMobilePhone::TMobilePhoneSubscriberId imsiId; + TRequestStatus status; + + phone.GetSubscriberId( status, imsiId ); + + User::WaitForRequest( status ); + + if( ! status.Int() ) + { + imsi = HBufC8::NewMaxLC( imsiId.Length() + KImsiId().Size() ); + TPtr8 imsiPtr(const_cast(imsi->Ptr()), 0, imsi->Size()); + + imsiNumber = CnvUtfConverter::ConvertFromUnicodeToUtf8L( imsiId ); + CleanupStack::PushL( imsiNumber ); + + imsiPtr.Copy( KImsiId() ); + imsiPtr.Append( *imsiNumber ); + CleanupStack::PopAndDestroy(); // imsiNumber + } + else + { + imsi = NULL; + } + } + else + { + imsi = NULL; + } + + + // Clean up whatever is in there + iIMSI->ResetAndDestroy(); + + if( imsi ) + { + // if we got it we wont try again + iIMSI->AppendL( imsi ); + CleanupStack::Pop(); // imsi + iGetImsi = EFalse; + } + + // Check for possible extra IMSI individual constraints + AppendExtendedIndividualConstraintsL(&phone); + + CleanupStack::PopAndDestroy(); // phone + CleanupStack::PopAndDestroy(); // cleanup item + CleanupStack::PopAndDestroy(); // etel server + + return *iIMSI; + +#else + HBufC8* imsi = NULL; + + if( iGetImsi ) + { + iGetImsi = EFalse; + _LIT8( KDefaultSerialNumber, "IMSI:123456789123456789" ); + imsi = KDefaultSerialNumber().AllocLC(); + iIMSI->AppendL( imsi ); + CleanupStack::Pop(); + AppendExtendedIndividualConstraintsL(); + } + + + return *iIMSI; +#endif // __WINS__ + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::AppendExtendedIndividualConstraintsL +// If the extension DLL exists it is loaded and used to obtain additional +// valid individual constraints +// ----------------------------------------------------------------------------- +void CDRMRightsServer::AppendExtendedIndividualConstraintsL(RMobilePhone* aMobilePhone) + { + // Load the externsion DLL + RLibrary lib; + +#ifndef RD_MULTIPLE_DRIVE + + if (lib.LoadRomLibrary(KDRMIndividualConstraintExtensionDll,KNullDesC)==KErrNone) + +#else //RD_MULTIPLE_DRIVE + + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + TFileName individualConstraindExtensionDll; + individualConstraindExtensionDll.Format( + KIndividualConstraintExtensionDll, (TUint)driveLetter ); + + if ( lib.LoadRomLibrary( individualConstraindExtensionDll, KNullDesC ) == KErrNone ) + +#endif + + { + CleanupClosePushL(lib); + + // Get first exported ordinal - factory method returning + // MDRMIndividualConstraintExtension* + TLibraryFunction factory = lib.Lookup(1); + + if (factory) + { + // Instantiate object + MDRMIndividualConstraintExtension* extendedConstraints = + reinterpret_cast(factory()); + + if (extendedConstraints) + { + CleanupStack::PushL(TCleanupItem(Release,extendedConstraints)); + extendedConstraints->AppendConstraintsL(*iIMSI,aMobilePhone); + CleanupStack::PopAndDestroy(extendedConstraints); //calls Release + } + } + + // unload library + CleanupStack::PopAndDestroy(&lib); //close + } + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::Release +// ----------------------------------------------------------------------------- +void CDRMRightsServer::Release(TAny* aIndividualConstraintExtension) + { + MDRMIndividualConstraintExtension* extendedConstraints = + reinterpret_cast(aIndividualConstraintExtension); + extendedConstraints->Release(); //free resources + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::HandleBackupEventL +// Handle Backup Events +// ----------------------------------------------------------------------------- +// + +void CDRMRightsServer::HandleBackupEventL( TInt aBackupEvent ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::BackupCalled\n\r")); + + //conn::TBURPartType eventType; + //conn::TBackupIncType incType; + TDriveList aDriveList; + + //RFileLogger::WriteFormat(KLogDir, KLogName, EFileLoggingModeAppend, _L8("backupevent: %d"), aBackupEvent); + + // If there is no operation going or state is normal + // Delete the client and handler + + if( aBackupEvent == conn::EBURUnset || + aBackupEvent & conn::EBURNormal ) + { + /* + if( aBackupEvent == conn::EBURUnset ) + { + RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Unset\n\r")); + } + else + { + RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Normal\n\r")); + } + */ + if( iActiveBackupClient ) + { + delete iActiveBackupClient; + iActiveBackupClient = NULL; + } + + if( iBackupHandler ) + { + delete iBackupHandler; + iBackupHandler = NULL; + } + } + else if( aBackupEvent & conn::EBURBackupFull || + aBackupEvent & conn::EBURRestoreFull ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Full\n\r")); + // ab handler + iBackupHandler = CDRMBackup::NewL( iDb, iFs ); + + // ab client + iActiveBackupClient = conn::CActiveBackupClient::NewL( iBackupHandler ); + + // Confirm that we have done everything if there even was anything to do + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm F \n\r")); + iActiveBackupClient->ConfirmReadyForBURL( KErrNone ); + } + else if( aBackupEvent & conn::EBURBackupPartial || + aBackupEvent & conn::EBURRestorePartial ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Partial\n\r")); + // ab handler + iBackupHandler = CDRMBackup::NewL( iDb, iFs ); + + // ab client + iActiveBackupClient = conn::CActiveBackupClient::NewL( iBackupHandler ); + + if( !iActiveBackupClient->DoesPartialBURAffectMeL() ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::NotMe\n\r")); + delete iActiveBackupClient; + iActiveBackupClient = NULL; + + delete iBackupHandler; + iBackupHandler = NULL; + } + else + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm P \n\r")); + // Confirm that we have done everything if there even was anything to do + iActiveBackupClient->ConfirmReadyForBURL( KErrNone ); + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm P Done \n\r")); + } + } + else + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Argument\n\r")); + // Unknown operation + User::Leave(KErrArgument); + } + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::WatchedObjectChangedL +// Handle Backup Events +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::WatchedObjectChangedL( const TDesC& aObject ) + { + DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL ->" ) ); + DRMLOG( aObject ); + + if ( aObject.Left( KDirIdentifier().Length() ) == KDirIdentifier && + !iDb->Updating() && iArmed ) + { +#ifdef _DEBUG + DRMLOG( _L( "RDB modified by outside party (DEBUG mode, not deleting the DB)" ) ); +#else + DRMLOG( _L( "RDB modified by outside party, deleting the DB" ) ); + iDb->MarkAsCorrupted(); + RStarterSession starter; + User::LeaveIfError( starter.Connect() ); + starter.Reset( RStarterSession::EDRMReset ); + starter.Close(); +#endif + } + else if ( aObject.Left( KProcIdentifier().Length() ) == KProcIdentifier && iArmed ) + { +#ifdef _DEBUG + DRMLOG( _L( "Peer process killed (DEBUG mode, not rebooting)" ) ); +#else + DRMLOG( _L( "Peer process killed, rebooting" ) ); + RStarterSession starter; + User::LeaveIfError( starter.Connect() ); + starter.Reset( RStarterSession::EDRMReset ); + starter.Close(); +#endif + } + + DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL <-" ) ); + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::HasActiveCountConstraint +// Check ID for active count constraint +// ----------------------------------------------------------------------------- +// +TBool CDRMRightsServer::HasActiveCountConstraint( const TDesC8& aContentId ) + { + TInt i; + TBool r = EFalse; + + for ( i = 0; r == EFalse && i < iActiveCountConstraints.Count(); i++ ) + { + if ( iActiveCountConstraints[i]->CompareF( aContentId ) == 0 ) + { + r = ETrue; + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::RemoveActiveCountConstraint +// Remove ID from count constraint list +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::RemoveActiveCountConstraint( const TDesC8& aContentId ) + { + TInt i; + TInt r = KErrNotFound; + HBufC8* id = NULL; + + for ( i = 0; r == KErrNotFound && i < iActiveCountConstraints.Count(); i++ ) + { + if ( iActiveCountConstraints[i]->CompareF( aContentId ) == 0 ) + { + r = i; + } + } + if ( r != KErrNotFound ) + { + id = iActiveCountConstraints[r]; + iActiveCountConstraints.Remove( r ); + delete id; + id = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::AddActiveCountConstraint +// Add ID to count constraint list +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::AddActiveCountConstraintL( const TDesC8& aContentId ) + { + if ( !HasActiveCountConstraint( aContentId ) ) + { + iActiveCountConstraints.AppendL( aContentId.AllocL() ); + } + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::StopWatchingL +// Delete the watchers +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::StopWatchingL() + { + iArmed = EFalse; + } + +#ifdef USE_RO_IMPORT +// ----------------------------------------------------------------------------- +// CDRMRightsServer::ImportRightsObjectsL +// Open the import directory and add all ROs that can be found there. ROs file +// names must end with .dr. Only OMA DRM 1.0 ROs in XML format are supported for +// security reasons +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::ImportRightsObjectsL( const TDesC& aImportDir ) + { + CDrmRightsParser* p; + HBufC8* d = NULL; + HBufC8* k = NULL; + RFs fs; + RFile file; + TInt size; + RPointerArray rights; + CDir* dir; + TFileName name; + TPtr8 ptr( NULL, 0 ); + TInt i; + TInt r = KErrNone; + TCleanupItem listCleanup(PointerArrayResetDestroyAndClose, + &rights); + TDRMUniqueID id; + TTime time; + + DRMLOG( _L( "CDRMRightsServer::ImportRightsObjectsL" ) ); + DRMLOG( aImportDir ); + __UHEAP_MARK; + GetSecureTime( time ); + p = CDrmRightsParser::NewL(); + CleanupStack::PushL( p ); + User::LeaveIfError( iFs.GetDir( aImportDir, KEntryAttNormal, + ESortNone, dir ) ); + CleanupStack::PushL( dir ); + for (i = 0; i < dir->Count(); i++) + { + name.Copy( aImportDir ); + name.Append( (*dir)[i].iName ); + if ( ( name.Length() > 3 && name.Right(3).CompareF( KDrSuffix ) == 0 ) ) + { + User::LeaveIfError( file.Open( iFs, name, EFileRead ) ); + CleanupClosePushL( file ); + User::LeaveIfError( file.Size( size ) ); + d = HBufC8::NewLC( size ); + ptr.Set( d->Des() ); + User::LeaveIfError( file.Read( ptr ) ); + p->ParseL( ptr, rights ); + if ( rights.Count() > 0 ) + { + k = NULL; + CleanupStack::PushL( listCleanup ); + CDRMPermission& permission = rights[0]->GetPermission(); + CDRMAsset& asset = rights[0]->GetAsset(); + + // Add RO only if no rights are available at all for this content + TRAP( r, k = iDb->GetDecryptionKeyL( *asset.iUid ) ); + if (k == NULL ) + { + iDb->AddDBEntryL( *asset.iUid, permission, asset.iKey, id ); + } + else + { + delete k; + } + CleanupStack::PopAndDestroy(); // listCleanup + } + CleanupStack::PopAndDestroy( 2 ); // d, file + iFs.Delete( name ); + } + } + CleanupStack::PopAndDestroy( 2 ); // dir, p + __UHEAP_MARKEND; + DRMLOG( _L( "CDRMRightsServer::ImportRightsObjectsL done" ) ); + } +#endif + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + + +TInt E32Main() + { + return Startup(); + } + + +// End of File