wmdrm/wmdrmengine/wmdrmfileserver/server/src/wmdrmfileserversession.cpp
changeset 0 95b198f216e5
child 84 b09186059647
--- /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 <f32file.h>
+#include <systemwarninglevels.hrh>
+#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<KFileNameSize>& 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<KFileNameSize> 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<KFileNameSize> 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<TInt>( 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<TInt>( 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<KFileNameSize> 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<KFileNameSize> 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<KFileNameSize> 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<KFileNameSize> 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<TTime> package( homeTime );
+    TPckg<TTime> 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<CWmDrmFileServer*>( const_cast<CServer2*>( CSession2::Server() ) );
+	}