diff -r 000000000000 -r 95b198f216e5 wmdrm/wmdrmengine/wmdrmfileserver/server/src/wmdrmfileserversession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wmdrm/wmdrmengine/wmdrmfileserver/server/src/wmdrmfileserversession.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,617 @@ +/* +* Copyright (c) 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: WMDRM Server implementation +* +*/ + + +#include +#include +#include "wmdrmfileserversession.h" +#include "wmdrmfileserver.h" + +#define _LOGGING_FILE L"wmdrmfileserver.txt" + +// Due to TCB capability logging can not be used +// #include "flogger.h" +// #include "logfn.h" + + +// rights server uid +const TUint32 KRightsServer = 0x101F51F2; +_LIT( KSecureStore, "securestore" ); +_LIT( KLicenseStore, "licstore" ); +_LIT( KDefaultNamespace, "hds"); + +_LIT( KStorePathTemplate, "%c:\\sys\\private\\2000B180\\%S\\%S\\"); + +// ======== LOCAL FUNCTIONS ======== + +// Implmentation from securitycheckutil.cpp with some reductions + +LOCAL_C TBool CheckFileName(const TFileName& aFileName, TChar aSystemDriveChar) + { + + if (aFileName.Length() > KMaxFileName) + { + return EFalse; + } + + // Check for full drive and path + TChar drive(aFileName[0]); + + _LIT(KDriveSeparator, ":\\"); + if (!drive.IsAlpha() || aFileName.Find(KDriveSeparator) != 1) + { + return EFalse; + } + + // Check for double slashes + _LIT(KDoubleSlash, "\\\\"); + if (aFileName.Find(KDoubleSlash) != KErrNotFound) + { + return EFalse; + } + + // Check for .. in the path + _LIT(KDoubleDotPath, "..\\"); + if (aFileName.Find(KDoubleDotPath) != KErrNotFound) + { + return EFalse; + } + + // Check for references to writable SwiCertstore + _LIT(KWritableSwiCertStore, ":\\Resource\\SwiCertstore"); + TBuf<32> writableSwiCertStorePath; + writableSwiCertStorePath.Append(aSystemDriveChar); + writableSwiCertStorePath.Append(KWritableSwiCertStore); + + if (aFileName.FindF(writableSwiCertStorePath) != KErrNotFound) + { + return EFalse; + } + + return ETrue; + } + + + +LOCAL_C TBool IsSubstedDriveL(RFs& aFs, const TFileName& aFileName) + { + TChar drvCh = aFileName[0]; + TInt drvNum; + User::LeaveIfError(RFs::CharToDrive(drvCh, drvNum)); + TDriveInfo drvInfo; + User::LeaveIfError(aFs.Drive(drvInfo, drvNum)); + //if the drive is subst'd return true + if(drvInfo.iDriveAtt & KDriveAttSubsted) + { + return ETrue; + } + return EFalse; + } + + + + +// --------------------------------------------------------------------------- +// Create a safe filename which can be used under the WMDRM file server +// root by filtering all illegal characters +// --------------------------------------------------------------------------- +// +LOCAL_C void CreateSafeFileNameL( + TFileName& aTarget, + const TBuf& aSource, + RFs &aFs ) + { + TInt i; + TChar c; + TBool suffix = ETrue; + + TInt driveNumber( RFs::GetSystemDrive() ); + TChar driveLetter; + User::LeaveIfError( RFs::DriveToChar( driveNumber, driveLetter ) ); + + TFileName storeRootFile; + storeRootFile.Format( KStoreRoot, (TUint)driveLetter ); + + if ( aSource.Length() + storeRootFile.Length() + 1 > aTarget.MaxLength() - aTarget.Length() ) + { + User::Leave( KErrArgument ); + } + + aTarget.Copy( storeRootFile ); + aTarget.Append( '\\' ); + for ( i = 0 ; i < aSource.Length(); i++ ) + { + c = aSource[i]; + + // Change all non-alphanumeric characters to underscores, + // except for the colon separating the file suffix + if ( !c.IsAlphaDigit() && !suffix ) + { + c = '_'; + } + + // Once the suffix colon has been processed, replace all non-alphanumeric characters + if ( suffix && c == '.' ) + { + suffix = EFalse; + } + aTarget.Append( c ); + } + + if( IsSubstedDriveL( aFs, aTarget ) || !CheckFileName( aTarget, driveLetter ) ) + { + User::Leave(KErrArgument); + } + } + +// --------------------------------------------------------------------------- +// Extract the path components from a full filename +// --------------------------------------------------------------------------- +// +LOCAL_C void GetPath( const TDesC& aFilename, TPtrC& aPath ) + { + TInt i = aFilename.Length() - 1; + while ( i >= 0 && aFilename[i] != '\\' ) + { + i--; + } + if ( aFilename[i] == '\\' ) + { + i++; + } + return aPath.Set( aFilename.Left( i ) ); + } + +// --------------------------------------------------------------------------- +// Check if system drive has <= KDRIVECCRITICALTHRESHOLD free space and in +// that case leave with KErrDiskFull +// --------------------------------------------------------------------------- +// +LOCAL_C void CheckFreeSpaceL( RFs &aFs, TInt aBytesToWrite ) + { + TVolumeInfo info; + User::LeaveIfError( aFs.Volume( info, aFs.GetSystemDrive() ) ); + if ( info.iFree - aBytesToWrite <= KDRIVECCRITICALTHRESHOLD ) + { + User::Leave( KErrDiskFull ); + } + } + +// ======== MEMBER FUNCTIONS ======== + +CWmDrmFileServerSession::CWmDrmFileServerSession() + { + //LOGFN( "CWmDrmFileServerSession::CWmDrmFileServerSession" ); + } + +CWmDrmFileServerSession::~CWmDrmFileServerSession() + { + //LOGFN( "CWmDrmFileServerSession::~CWmDrmFileServerSession" ); + iFile.Close(); + } + +TInt CWmDrmFileServerSession::OpenL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TFileName path; + TBuf fileName; + + //LOGFNR( "CWmDrmFileServerSession::OpenL", r ); + __UHEAP_MARK; + if ( aMessage.GetDesLength( 0 ) > KFileNameSize ) + { + User::Leave( KErrArgument ); + } + iFile.Close(); + aMessage.ReadL( 0, fileName ); + CreateSafeFileNameL( path, fileName, Server().Fs() ); + //LOG( path ); + r = iFile.Open( Server().Fs(), path, EFileRead | EFileWrite ); + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::CreateL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TFileName path; + TBuf fileName; + TPtrC folders( NULL, 0 ); + + //LOGFNR( "CWmDrmFileServerSession::CreateL", r ); + __UHEAP_MARK; + if ( aMessage.GetDesLength( 0 ) > KFileNameSize ) + { + User::Leave( KErrArgument ); + } + iFile.Close(); + aMessage.ReadL( 0, fileName ); + //LOG( fileName ); + CreateSafeFileNameL( path, fileName, Server().Fs() ); + GetPath( path, folders ); + + CheckFreeSpaceL( Server().Fs(), 0 ); + + Server().Fs().MkDirAll( folders ); + //LOG( path ); + r = iFile.Replace( Server().Fs(), path, EFileRead | EFileWrite ); + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::ReadL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + RBuf8 buf; + TInt amountRead = 0; + TInt pos = 0; + + //LOGFNR( "CWmDrmFileServerSession::ReadL", r ); + __UHEAP_MARK; + if ( iFile.SubSessionHandle() == KNullHandle ) + { + User::Leave( KErrNotReady ); + } + + buf.CreateL( aMessage.GetDesMaxLengthL( 0 ) ); + CleanupClosePushL( buf ); + iFile.Seek( ESeekStart, pos ); + r = iFile.Read( buf ); + if ( r == KErrNone ) + { + aMessage.WriteL( 0, buf ); + amountRead = buf.Size(); + } + aMessage.WriteL( 1, TPckg( amountRead ) ); + //LOG2( "Read %d bytes", amountRead ); + CleanupStack::PopAndDestroy(); // buf + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::WriteL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + RBuf8 buf; + TInt pos = 0; + + //LOGFNR( "CWmDrmFileServerSession::WriteL", r ); + __UHEAP_MARK; + if ( iFile.SubSessionHandle() == KNullHandle ) + { + User::Leave( KErrNotReady ); + } + + CheckFreeSpaceL( Server().Fs(), aMessage.GetDesLengthL( 0 ) ); + + buf.CreateL( aMessage.GetDesLengthL( 0 ) ); + CleanupClosePushL( buf ); + aMessage.ReadL( 0, buf ); + iFile.Seek( ESeekStart, pos ); + iFile.SetSize( 0 ); + r = iFile.Write( buf ); + CleanupStack::PopAndDestroy(); // buf + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::SizeL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TInt size; + + //LOGFNR( "CWmDrmFileServerSession::SizeL", r ); + __UHEAP_MARK; + if ( iFile.SubSessionHandle() == KNullHandle ) + { + User::Leave( KErrNotReady ); + } + r = iFile.Size( size ); + if ( r == KErrNone ) + { + aMessage.WriteL( 0, TPckg( size ) ); + } + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::IsOpenL( const RMessage2& /*aMessage*/ ) + { + TInt r = KErrNone; + + //LOGFNR( "CWmDrmFileServerSession::IsOpenL", r ); + if ( iFile.SubSessionHandle() == KNullHandle ) + { + r = KErrNotReady; + } + return r; + } + +TInt CWmDrmFileServerSession::CloseFileL( const RMessage2& /*aMessage*/ ) + { + TInt r = KErrNone; + + //LOGFNR( "CWmDrmFileServerSession::CloseFileL", r ); + iFile.Close(); + return r; + } + +TInt CWmDrmFileServerSession::DeleteL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TFileName path; + TBuf fileName; + + //LOGFNR( "CWmDrmFileServerSession::DeleteL", r ); + __UHEAP_MARK; + if ( aMessage.GetDesLength( 0 ) > KFileNameSize ) + { + User::Leave( KErrArgument ); + } + aMessage.ReadL( 0, fileName ); + CreateSafeFileNameL( path, fileName, Server().Fs() ); + r = Server().Fs().Delete( path ); + //LOG( path ); + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::MkDirAllL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TFileName path; + TBuf fileName; + TUint att; + + //LOGFNR( "CWmDrmFileServerSession::MkDirAllL", r ); + __UHEAP_MARK; + if ( aMessage.GetDesLength( 0 ) > KFileNameSize ) + { + User::Leave( KErrArgument ); + } + aMessage.ReadL( 0, fileName ); + CreateSafeFileNameL( path, fileName, Server().Fs() ); + //LOG( path ); + if ( !aMessage.Int1() && ( r = Server().Fs().Att( path, att ) ) != KErrNone ) + { + User::Leave( r ); + } + + CheckFreeSpaceL( Server().Fs(), 0 ); + + r = Server().Fs().MkDirAll( path ); + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::RmDirAllL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TFileName path; + TBuf fileName; + CFileMan* fileMan; + + //LOGFNR( "CWmDrmFileServerSession::RmDirAllL", r ); + __UHEAP_MARK; + if ( aMessage.GetDesLength( 0 ) > KFileNameSize ) + { + User::Leave( KErrArgument ); + } + fileMan = CFileMan::NewL( Server().Fs() ); + CleanupStack::PushL( fileMan ); + aMessage.ReadL( 0, fileName ); + CreateSafeFileNameL( path, fileName, Server().Fs() ); + r = fileMan->RmDir( path ); + //LOG( path ); + CleanupStack::PopAndDestroy(); // fileMan + __UHEAP_MARKEND; + return r; + } + +TInt CWmDrmFileServerSession::RmDirL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TFileName path; + TBuf fileName; + + //LOGFNR( "CWmDrmFileServerSession::RmDirL", r ); + __UHEAP_MARK; + if ( aMessage.GetDesLength( 0 ) > KFileNameSize ) + { + User::Leave( KErrArgument ); + } + aMessage.ReadL( 0, fileName ); + CreateSafeFileNameL( path, fileName, Server().Fs() ); + r = Server().Fs().RmDir( path ); + //LOG( path ); + __UHEAP_MARKEND; + return r; + } + + +TInt CWmDrmFileServerSession::UpdateSecureTimeL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TTime homeTime; + TTime utcTime; + RThread client; + + TPckg package( homeTime ); + TPckg package2( utcTime ); + + // Get the client: + aMessage.ClientL( client ); + CleanupClosePushL( client ); + + // Check client, if client is not the rights server, access denied: + _LIT_SECURITY_POLICY_S0(swSidCheck2, KRightsServer); + + if( !swSidCheck2().CheckPolicy(client) ) + { + User::Leave( KErrAccessDenied ); + } + + CleanupStack::PopAndDestroy( &client ); + + aMessage.ReadL( 0, package ); + aMessage.ReadL( 1, package2 ); + + // Set the secure time: + User::LeaveIfError( User::SetUTCTimeSecure( utcTime ) ); + //User::LeaveIfError( User::SetHomeTimeSecure( homeTime ) ); + + return r; + } + +TInt CWmDrmFileServerSession::DeleteRightsL( const RMessage2& /*aMessage*/ ) + { + TInt r = KErrNone; + TInt finalErr = KErrNone; + TFileName storeRootFile; + CFileMan* fileMan = NULL; + + //LOGFNR( "CWmDrmFileServerSession::DeleteRightsL", r ); + __UHEAP_MARK; + fileMan = CFileMan::NewL( Server().Fs() ); + CleanupStack::PushL( fileMan ); + // Remove the stores: + TInt driveNumber( RFs::GetSystemDrive() ); + TChar driveLetter; + User::LeaveIfError( RFs::DriveToChar( driveNumber, driveLetter ) ); + + storeRootFile.Format( KStorePathTemplate, (TUint)driveLetter, &KDefaultNamespace, &KLicenseStore ); + //r = Server().Fs().RmDir( storeRootFile ); + r = fileMan->RmDir( storeRootFile ); + if( r < KErrNone ) + { + finalErr = r; + } + + storeRootFile.Format( KStorePathTemplate, (TUint)driveLetter, &KDefaultNamespace, &KSecureStore ); + //r = Server().Fs().RmDir( storeRootFile ); + r = fileMan->RmDir( storeRootFile ); + if( !finalErr && r < KErrNone ) + { + finalErr = r; + } + + CleanupStack::PopAndDestroy( fileMan ); + __UHEAP_MARKEND; + return finalErr; + } + +// --------------------------------------------------------------------------- +// Main service function. All services require DRM capability! +// --------------------------------------------------------------------------- +// +void CWmDrmFileServerSession::ServiceL( const RMessage2& aMessage ) + { + TInt r = KErrNone; + TInt trap = KErrNone; + _LIT_SECURITY_POLICY_C1(drmCheck, ECapabilityDRM); + RThread client; + + //LOGFNR( "CWmDrmFileServerSession::ServiceL", r ); +#ifdef _LOGGING + TInt c; + TInt s; + c = User::AllocSize(s); + //LOG3( "Memory: %d cells, %d bytes allocated", c, s ); +#endif + + aMessage.ClientL( client ); + if ( !drmCheck().CheckPolicy( client ) ) + { + r = KErrAccessDenied; + } + else + { + switch ( aMessage.Function() ) + { + case EFsOpen: + TRAP( trap, r = OpenL( aMessage ) ); + break; + case EFsCreate: + TRAP( trap, r = CreateL( aMessage ) ); + break; + case EFsRead: + TRAP( trap, r = ReadL( aMessage ) ); + break; + case EFsWrite: + TRAP( trap, r = WriteL( aMessage ) ); + break; + case EFsSize: + TRAP( trap, r = SizeL( aMessage ) ); + break; + case EFsDelete: + TRAP( trap, r = DeleteL( aMessage ) ); + break; + case EFsIsOpen: + TRAP( trap, r = IsOpenL( aMessage ) ); + break; + case EFsCloseFile: + TRAP( trap, r = CloseFileL( aMessage ) ); + break; + case EFsMkDirAll: + TRAP( trap, r = MkDirAllL( aMessage ) ); + break; + case EFsRmDirAll: + TRAP( trap, r = RmDirAllL( aMessage ) ); + break; + case EFsRmDir: + TRAP( trap, r = RmDirL( aMessage ) ); + break; + case EFsUpdateSecureTime: + TRAP( trap, r = UpdateSecureTimeL( aMessage ) ); + break; + case EFsDeleteRights: + TRAP( trap, r = DeleteRightsL( aMessage ) ); + break; + default: + PanicClient( aMessage, EPanicIllegalFunction ); + break; + } + if ( trap != KErrNone ) + { + r = trap; + } + } + client.Close(); + if ( !aMessage.IsNull() ) + { + aMessage.Complete( r ); + } + } + +void CWmDrmFileServerSession::ServiceError( const RMessage2& aMessage, TInt aError ) + { + //LOGFN( "CWmDrmFileServerSession::ServiceError" ); + //LOG2( "** Error: %d", aError ); + if ( aError == KErrBadDescriptor ) + { + PanicClient( aMessage, EPanicBadDescriptor ); + } + if ( !aMessage.IsNull() ) + { + CSession2::ServiceError( aMessage, aError ); + } + } + +CWmDrmFileServer& CWmDrmFileServerSession::Server() + { + return *static_cast( const_cast( CSession2::Server() ) ); + }