diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/dbms/sdbms/Sd_Sess2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/persistentstorage/dbms/sdbms/Sd_Sess2.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,547 @@ +// Copyright (c) 2004-2009 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: +// DBMS server-session and support classes - "DBMS security" related - full support +// +// + +#include +#include "D32Strings.h" +#include "SD_STD.H" +#include "Sd_DbList.h" + +using namespace DBSC; + +CDbsSession::CDbsSession() : + iDbPolicyRqColl(TLinearOrder< TPair > (&Compare)) + { + } + +/** +New "DBMS security" related messages processed here! +@param aMessage DBMS server message +@param aDbsFunction DBMS server function code +@return An error code (< 0) or a DBMS server session object handle (EDbsDatabase, EDbsIncremental,...). +*/ +TInt CDbsSession::ExtServiceL(const RMessage2& aMessage, TDbsFunction aDbsFunction) + { + TInt handle = 0; + switch(aDbsFunction) + { + case EDbsCreateDatabase: + handle=CreateDatabaseL(aMessage); + break; + case EDbsDatabaseList: + handle=GetDatabaseListL(aMessage); + break; + case EDbsCopyDatabase: + CopyDatabaseL(aMessage); + break; + case EDbsDeleteDatabase: + DeleteDatabaseL(aMessage); + break; + case EDbsGetSecurityPolicy: + GetSecurityPolicyL(aMessage); + break; + case EDbsGetBackupPath: + GetBackupPathL(aMessage); + break; + case EDbsGetBackupPaths: + handle=GetBackupPathsL(aMessage); + break; + default: + handle = KErrNotSupported; + break; + } + return handle; + } + +/** +Extracts aMessage's "aIndex" argument (which is expected to be a file name) and +stores it to CDbsServer::iFileName data member. +@param aIndex The index of RMessage parameter +@param aMessage +@return A descriptor of the file name,extracted from aMessage and stored in CDbsServer::iFileName. +*/ +const TDesC& CDbsSession::ReadFileNameL(TInt aIndex, const RMessage2& aMessage) + { + TDes& name = Server().FileName(); + aMessage.ReadL(aIndex, name); + return name; + } + +/** +Extracts database name (aMessage's arg 0) and database format string (aMessage's arg 1) +and use them to extract database properties, such as: database UID, access type (secure/non-secure), +full database file path, database format string, drive number. +@return A pointer to a TDbProps object, which contains some properties, extracted from the database name. +*/ +TDbProps* CDbsSession::ExtractDbPropsLC(const RMessage2& aMessage) + { + const TDesC& dbName = ReadFileNameL(0, aMessage); + const TDesC& dbFormat = ReadName0L(1, aMessage); + return Server().DbPropsFactory().ExtractLC(dbName, dbFormat); + } + +/** +This method creates new EDbsDatabase type object. +The related MPolicy interface will be retrieved and +put together with the EDbsDatabase object in TEntry list. + +The initial contact for a database. Open a database source +return the database handle for the client +*/ +TInt CDbsSession::OpenDatabaseL(const RMessage2& aMessage) + { + TDbProps* dbProps = ExtractDbPropsLC(aMessage); + const MPolicy* policy = Server().PolicyProxy().DbPolicyL(dbProps->iDbPolicyRequest); + Server().PolicyProxy().CheckL(aMessage, *policy); + TInt dbHandle = DoOpenDatabaseL(aMessage, *dbProps); + CleanupStack::PopAndDestroy(dbProps); + return dbHandle; + } + + +/** +SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method. +Opens a database. It is used by both: OpenDatabase() and CreateDatabase() methods. +@param aMessage DBMS server message:EDbsCreateDatabase or EDbsOpenDatabase. +@param aDbProps A TDbProps object created from the database name and format string. +@return A handle to the opened/created database object. +@leave One of the system-wide error codes. +*/ +TInt CDbsSession::DoOpenDatabaseL(const RMessage2& aMessage, const TDbProps& aDbProps) + { + CDbsConnection* dbConnection = Sources().OpenLC(Server().Fs(), aDbProps.iPath, aDbProps.iFormatStr); + CDbObject* dbObj = DoAuthenticateL(dbConnection, aMessage); + dbConnection->Attach(dbObj); + CleanupStack::Pop(dbConnection); + + //dbObj does not have to be pushed in the cleanup stack! + //NewDbEntryL() will take care of its destruction, if the database entry cannot be created. + //NewDbEntryL() will destroy the connection also in this case. + TInt dbHandle = 0; + NewDbEntryL(dbObj, aDbProps.iDbPolicyRequest, dbHandle); + return dbHandle; + } + +//SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method. +//Authenticates a database. +CDbObject* CDbsSession::DoAuthenticateL(CDbsConnection* aDbsConnection, const RMessage2&) + { + __ASSERT(aDbsConnection); + CDbSource& src = aDbsConnection->Source().Source(); + return src.AuthenticateL(); + } + + +//Adds a new database entry to the session list of database session objects. +void CDbsSession::NewDbEntryL(CDbObject* aDbObject, const TDbPolicyRequest& aDbPolicyRequest, TInt& aDbHandle) + { + __ASSERT(aDbObject); + const MPolicy* policy = Server().PolicyProxy().DbPolicyL(aDbPolicyRequest); + + aDbHandle = DoAdd(aDbObject, EDbsDatabase, policy); + + //Store the database uid for later use + TInt err = iDbPolicyRqColl.Insert(aDbHandle, aDbPolicyRequest); + if(err != KErrNone) + {//If iDbPolicyRqColl.Insert() fails, then remove the object from TEntry list and then return. + TEntry& e = Object(aDbHandle); + Free(e); + User::Leave(err); + } + } + +/** +Converts RDbs::TPolicyType parameter value to the internally used DBSC::TPolicyType value. +@param aPolicyType Security policy type - client side +@return Security policy type used on the server side. +@leave KErrArgument if it is an invalid security policy type +*/ +static TPolicyType ConvertPolicyTypeL(RDbs::TPolicyType aPolicyType) + { + TPolicyType policyType = static_cast (1 << aPolicyType); + if(policyType > EPTLast || policyType <= EPTNone) + { + __LEAVE(KErrArgument); + } + return policyType; + } + +/** +Creates secure shared database. +@param aMessage DBMS server message: EDbsCreateDatabase. +@return A handle to the created database object. +@leave One of the system-wide error codes, including: + KErrNotSupported An attempt to create non-secure shared database + KErrAlreadyExists The database with the supplied name already exists +*/ +TInt CDbsSession::CreateDatabaseL(const RMessage2& aMessage) + { + TDbProps* dbProps = ExtractDbPropsLC(aMessage); + if(dbProps->iDbPolicyRequest.iAccessType == EATNonSecure) + {//This method works only for secure shared databases + __LEAVE(KErrNotSupported); + } + const MPolicy* policy = Server().PolicyProxy().DbPolicyL(dbProps->iDbPolicyRequest); + Server().PolicyProxy().CheckL(aMessage, *policy); + //Leave if the file is already there + ::TEntry fileEntry; + TBool dbFileExist = Server().Fs().Entry(dbProps->iPath, fileEntry) == KErrNone; + if(dbFileExist) + { + __LEAVE(KErrAlreadyExists); + } + TInt dbHandle = 0; + TRAPD(err, dbHandle = DoCreateDatabaseL(aMessage, *dbProps)); + if(err != KErrNone) + {//Cleanup if the creation fails + // Although the file delete below could return at error since we are + // already on an error-path a design decision has been made to ignore the + // error in favor of the one returned by DoCreateDatabaseL() + + // If a debug build - record error + TInt fileDeleteErr = Server().Fs().Delete(dbProps->iPath); + #ifdef _DEBUG + if (fileDeleteErr != KErrNone) + { + RDebug::Print(_L("CDbsSession::CreateDatabaseL - Failed to delete file. Error = %d"), fileDeleteErr); + } + #endif + + __LEAVE(err); + } + CleanupStack::PopAndDestroy(dbProps); + return dbHandle; + } + +//Creates secure shared database. +//Originaly, the database were always created on the client side, using ::CreateDatabaseL() call. +//I am not very sure how this function works and prefer to call ::CreateDatabaseL() to create +//the database on the server side, then delete it and the open it in the same way, as it +//worked before for opening/sharing databases on the server side. +TInt CDbsSession::DoCreateDatabaseL(const RMessage2& aMessage, const TDbProps& aDbProps) + { + CDbDatabase* db = ::CreateDatabaseL(TDbFormat::ECreate, Server().Fs(), aDbProps.iPath, aDbProps.iFormatStr); + delete db; + TInt dbHandle = DoOpenDatabaseL(aMessage, aDbProps); + return dbHandle; + } + +/** +Copies an existing secure shared database to a new database. +The new database will have the same security policy as the old one. +@param aMessage DBMS server message (EDbsCopyDatabase) +@leave One of the system-wide error codes, including KErrArgument - a null uid supplied + as an argument. +*/ +void CDbsSession::CopyDatabaseL(const RMessage2& aMessage) + { + RDbPropsFactory& dbPropsFactory = Server().DbPropsFactory(); + TUid uid; + uid.iUid = aMessage.Int2(); + if(uid == KNullUid) + { + __LEAVE(KErrArgument); + } + //Do not change the order, because ReadFileNameL() uses the same place to store the names. + const TDesC& srcDbName = ReadFileNameL(0, aMessage); + TDbProps* srcDbProps = dbPropsFactory.ExtractLC(srcDbName, uid); + const TDesC& destDbName = ReadFileNameL(1, aMessage); + TDbProps* destDbProps = dbPropsFactory.ExtractLC(destDbName, uid); + + const MPolicy* policy = Server().PolicyProxy().DbPolicyL(srcDbProps->iDbPolicyRequest); + Server().PolicyProxy().CheckL(aMessage, *policy); + + CFileMan* fileMan = CFileMan::NewL(Server().Fs()); + CleanupStack::PushL(fileMan); + __LEAVE_IF_ERROR(fileMan->Copy(srcDbProps->iPath, destDbProps->iPath, 0)); + //"Copy" operation executed without errors. Now it is a time to turn off the read-only + //flag of the target file (which may be on if the source files is on a read-only drive) + __LEAVE_IF_ERROR(Server().Fs().SetAtt(destDbProps->iPath, 0, KEntryAttReadOnly)); + CleanupStack::PopAndDestroy(3);//srcDbProps, destDbProps, fileMan + } + +/** +Deletes secure shared database +@param aMessage DBMS server message (EDbsDeleteDatabase) +@leave One of the system-wide error codes, including KErrArgument - a null uid supplied + as an argument. +*/ +void CDbsSession::DeleteDatabaseL(const RMessage2& aMessage) + { + TUid uid; + uid.iUid = aMessage.Int1(); + if(uid == KNullUid) + { + __LEAVE(KErrArgument); + } + const TDesC& dbName = ReadFileNameL(0, aMessage); + TDbProps* dbProps = Server().DbPropsFactory().ExtractLC(dbName, uid); + const MPolicy* policy = Server().PolicyProxy().DbPolicyL(dbProps->iDbPolicyRequest); + Server().PolicyProxy().CheckL(aMessage, *policy); + __LEAVE_IF_ERROR(Server().Fs().Delete(dbProps->iPath)); + CleanupStack::PopAndDestroy(dbProps); + } + +/** +Gets the list of names of datatbases, which have the same uid. +@param aMessage DBMS server message (EDbsDatabaseList) +@return A stream handle to a stream with the database names found. +@leave One of the system-wide error codes, including KErrArgument - a null uid supplied + as an argument. +*/ +TInt CDbsSession::GetDatabaseListL(const RMessage2& aMessage) + { + CDbNamesFactory* dbNamesFactory = CDbNamesFactory::NewLC(); + TDriveNumber driveNumber; + TDbPolicyRequest dbPolicyRequest; + CDbNamesFactory::ExtractArgs(aMessage, driveNumber, dbPolicyRequest); + if(dbPolicyRequest.iUid == KNullUid) + { + __LEAVE(KErrArgument); + } + const MPolicy* policy = Server().PolicyProxy().DbPolicyL(dbPolicyRequest); + Server().PolicyProxy().CheckL(aMessage, *policy); + CDbDatabaseNames* dbNames = dbNamesFactory->DbNamesLC(driveNumber, dbPolicyRequest, Server().DbPropsFactory(), Server().Fs()); + //NewStreamL() will take care about destroying dbNames. + TInt streamHandle = NewStreamL(dbNames, Externalizer(dbNames), aMessage, policy); + CleanupStack::PopAndDestroy(dbNamesFactory); + return streamHandle; + } + +/** +Gets database/table security policy. +@param aMessage DBMS server message (EDbsGetSecurityPolicy) +@leave One of the system-wide error codes, including KErrArgument - a null uid supplied + as an argument. +*/ +void CDbsSession::GetSecurityPolicyL(const RMessage2& aMessage) + { + //No security policy check. + TUid dbUid = TUid::Uid(aMessage.Int0()); + if(dbUid == KNullUid) + { + __LEAVE(KErrArgument); + } + TPolicyType policyTypeRq = ::ConvertPolicyTypeL(static_cast (aMessage.Int1() & ~KTablePolicyMaskBit)); + TBool tblPolicyRq = aMessage.Int1() & KTablePolicyMaskBit; + if(tblPolicyRq) + { + ReadName0L(2, aMessage); + if(Server().Name0() == KNullDesC) + { + __LEAVE(KErrArgument); + } + } + TDbPolicyRequest dbPolicyRequest; + dbPolicyRequest.iUid = dbUid; + dbPolicyRequest.iAccessType = EATSecure; + const MPolicy* policy = tblPolicyRq ? Server().PolicyProxy().TblPolicyL(dbPolicyRequest, Server().Name0()) : + Server().PolicyProxy().DbPolicyL(dbPolicyRequest); + __ASSERT(policy); + TSecurityPolicy secPolicy; + __LEAVE_IF_ERROR(policy->Get(policyTypeRq, secPolicy)); + aMessage.WriteL(3, secPolicy.Package()); + } + +/** +The function extracts backup&restore process SID from aMessage argument (parameter 0). +@param aMessage DBMS server message - EDbsGetBackupPath or EDbsGetBackupPaths. +@return Backup&restore process SID +@leave KErrArgument 0 or ECapability_None backup&restore process SID +@internalComponent +*/ +static TSecureId BackupSIDL(const RMessage2& aMessage) + { + TSecureId backupSID = TSecureId(aMessage.Int0()); + if(backupSID.iId == 0 || backupSID.iId == (TUint32)ECapability_None) + { + __LEAVE(KErrArgument); + } + return backupSID; + } + +/** +The function extracts database security policy UID from aMessage argument (parameter 1). +@param aMessage DBMS server message - EDbsGetBackupPath or EDbsGetBackupPaths. +@return Database security policy UID +@leave KErrArgument Null database security policy UID +@internalComponent +*/ +static TUid SecurityPolicyUidL(const RMessage2& aMessage) + { + TUid dbUid = TUid::Uid(aMessage.Int1()); + if(dbUid == KNullUid) + { + __LEAVE(KErrArgument); + } + return dbUid; + } + +/** +The function gets the backup&restore process SID from the related database security policy, +identified by aDbUid argument. +@param aPolicyProxy A reference to CPolicyProxy object, which might be asked for particular + database or table policy. +@param aBackupSID Backup&restore process SID, extracted from RMessage2 object. +@param aDbUid Database security policy UID, extracted from RMessage2 object. +@return Backup&restore process SID, which is part of the database security policy. +@leave KErrPermissionDenied - the supplied process SID does not match the database backup& + restore SID or the database backup&restore SID is 0 or ECapability_None. +@internalComponent +*/ +static TSecureId RegisteredBackupSIDL(CPolicyProxy& aPolicyProxy, TSecureId aBackupSID, TUid aDbUid) + { + TSecureId regBackupSID = aPolicyProxy.BackupSIDL(aDbUid); + if((regBackupSID == 0 || regBackupSID == (TUint32)ECapability_None) || aBackupSID != regBackupSID) + { + __LEAVE(KErrPermissionDenied); + } + return regBackupSID; + } + +/** +The method will return via aMessage argument the full path to the secure shared database, +which name is packed in aMessage argument too. +@param aMessage DBMS server message (EDbsGetBackupPath) +@leave One of the system-wide error codes, including: + - KErrArgument - 0 or ECapability_None process SID, null UID, + null or invalid database name, + the database is not secure shared database; + - KErrNotFound - the database file does not exist; + - KErrPermissionDenied - the supplied process SID does not match the database backup& + restore SID or the database backup&restore SID is 0 or ECapability_None. +@deprecated +*/ +void CDbsSession::GetBackupPathL(const RMessage2& aMessage) + { + //Backup&restore process SID + TSecureId backupSID = ::BackupSIDL(aMessage); + //Security policy UID + TUid dbUid = ::SecurityPolicyUidL(aMessage); + //Database name and drive, format: :. + ReadName0L(2, aMessage); + if(Server().Name0() == KNullDesC) + { + __LEAVE(KErrArgument); + } + //Database path + RDbPropsFactory& dbPropsFactory = Server().DbPropsFactory(); + TDbProps* dbProps = dbPropsFactory.ExtractLC(Server().Name0(), dbUid); + if(dbProps->iDbPolicyRequest.iAccessType != EATSecure) + { + __LEAVE(KErrArgument); + } + //Check if the database file exists + ::TEntry fileEntry; + TBool dbFileExist = Server().Fs().Entry(dbProps->iPath, fileEntry) == KErrNone; + if(!dbFileExist) + { + __LEAVE(KErrNotFound); + } + //Get and check backup&restore SID + TSecureId regBackupSID = ::RegisteredBackupSIDL(Server().PolicyProxy(), backupSID, dbUid); + // + aMessage.WriteL(3, dbProps->iPath); + // + CleanupStack::PopAndDestroy(dbProps); + } + +/** +This function processes "aFileEntries" array, which is a result of TFindFile::FindWildByDir() +or TFindFile::FindWild() calls. In a loop the function will get an element from "aFileEntries" +array, copy it to a temporary string adding the drive and the path, and will add that string +to "aDatabasePaths" array. +Note: If the created full file path length is bigger than KDbMaxStrLen characters, then the + string will not be added to "aDatabasePaths" array! +@param aFileEntries An array of file names, result of TFindFile::FindWildByDir() or + TFindFile::FindWild() calls. +@param aFileSpec A string, containing the drive and the directory of the file names in + aFileEntries array. +@param aDatabasePaths Output argument. Each file name from aFileEntries array will be "decorated" + with the drive and path and then the created new string will be added to + aDatabasePaths array. +@leave One of the system-wide error codes, including KErrNoMemory. +@internalComponent +*/ +static void ProcessFileEntriesL(CDir& aFileEntries, const TDesC& aFileSpec, + CDbStrings& aDatabasePaths) + { + TParse parse; + __LEAVE_IF_ERROR(parse.Set(aFileSpec, NULL, NULL)); + TInt cnt = aFileEntries.Count(); + for(TInt i=0;i