--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/sdbms/Sd_Sess2.cpp Fri Jan 22 11:06:30 2010 +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 <s32file.h>
+#include "D32Strings.h"
+#include "SD_STD.H"
+#include "Sd_DbList.h"
+
+using namespace DBSC;
+
+CDbsSession::CDbsSession() :
+ iDbPolicyRqColl(TLinearOrder< TPair<TInt, TDbPolicyRequest> > (&Compare<TInt, TDbPolicyRequest>))
+ {
+ }
+
+/**
+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 <TPolicyType> (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 <RDbs::TPolicyType> (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: <drive>:<name>.<ext>
+ 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<cnt;++i)
+ {
+ TFileName fileName;
+ fileName.Copy(parse.DriveAndPath());
+ const ::TEntry& entry = aFileEntries[i];
+ fileName.Append(entry.iName);
+ if(fileName.Length() < KDbMaxStrLen)
+ {
+ aDatabasePaths.AddL(fileName);
+ }
+ }
+ }
+
+/**
+Gets a list of paths of the databases, which have the same security policy uid.
+@param aMessage DBMS server message (EDbsGetBackupPaths)
+@return A stream handle to a stream with the database names found.
+@leave One of the system-wide error codes, including:
+ - KErrArgument - 0 or ECapability_None process SID, null database security policy UID;
+ - KErrPermissionDenied - the supplied process SID does not match databases backup&
+ restore SID or databases backup&restore SID is 0 or ECapability_None.
+*/
+TInt CDbsSession::GetBackupPathsL(const RMessage2& aMessage)
+ {
+ //Backup&restore process SID
+ TSecureId backupSID = ::BackupSIDL(aMessage);
+ //Security policy UID
+ TUid dbUid = ::SecurityPolicyUidL(aMessage);
+ //Get and check backup&restore SID
+ TSecureId regBackupSID = ::RegisteredBackupSIDL(Server().PolicyProxy(), backupSID, dbUid);
+ //Get the related database security policy
+ TDbPolicyRequest dbPolicyRequest = {dbUid, EATSecure};
+ const MPolicy* policy = Server().PolicyProxy().DbPolicyL(dbPolicyRequest);
+ //
+ CDbStrings* dbPaths = CDbStrings::NewLC();
+ //DBMS server - private data path. CDbServer::iFileName used as a storage for the path.
+ __LEAVE_IF_ERROR(Server().Fs().PrivatePath(Server().FileName()));
+ //Construct search pattern. CDbServer::iName1 used as a storage for the search pattern.
+ RDbPropsFactory::ConstructCommonPart(dbUid, Server().Name1());
+ Server().Name1().Append('*');
+ //Search....
+ TFindFile findFile(Server().Fs());
+ CDir* fileEntries = NULL;
+ TInt err = findFile.FindWildByDir(Server().Name1(), Server().FileName(), fileEntries);
+ if(err == KErrNone)
+ {
+ do
+ {
+ __ASSERT(fileEntries);
+ CleanupStack::PushL(fileEntries);
+ ::ProcessFileEntriesL(*fileEntries, findFile.File(), *dbPaths);
+ CleanupStack::PopAndDestroy(fileEntries);
+ fileEntries = NULL;
+ } while(findFile.FindWild(fileEntries) == KErrNone);
+ }
+ if(err != KErrNotFound && err != KErrNone)
+ {
+ __LEAVE(err);
+ }
+ //NewStreamL() will take care about destroying dbPaths.
+ TInt streamHandle = NewStreamL(dbPaths, Externalizer(dbPaths), aMessage, policy);
+ return streamHandle;
+ }