sl@0: /* sl@0: * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Common security functions sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: sl@0: #include "securityutils.h" sl@0: sl@0: #include sl@0: sl@0: // Extracts the next sub-dir name, i.e. "directory1" for "directory1\directory2\...". As a second parameter, returns the remaining path without the leading slash sl@0: // Return ETrue iff a directory was found in the path sl@0: TBool GetNextDirNameL(const TPtrC& aPath, TPtrC& aNextDir, TPtrC& aRemainingPath) sl@0: { sl@0: TInt nextSlashPos = aPath.Locate('\\'); sl@0: if (nextSlashPos < 0) sl@0: return EFalse; sl@0: sl@0: aNextDir.Set(aPath.Left(nextSlashPos)); sl@0: TPtrC remainingPath = nextSlashPos < aPath.Length() - 1 ? aPath.Mid(nextSlashPos + 1) : TPtrC(); sl@0: aRemainingPath.Set(remainingPath); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: TCapabilitySet PrivateModificationRequiredCapabilitiesL(const TDesC& aPrivateSubPath, TSecureId aClientSid) sl@0: { sl@0: TPtrC privateSubDirName; sl@0: TPtrC remainingSubPath; sl@0: TBool nextDirAvailable = GetNextDirNameL(aPrivateSubPath, privateSubDirName, remainingSubPath); sl@0: // Filter out paths which do not have a /private/ form - require TCB for them sl@0: // First, filter out files directly under the /private directory sl@0: if (!nextDirAvailable) sl@0: return TCapabilitySet(ECapabilityTCB); sl@0: sl@0: if (privateSubDirName.Length() != 8) sl@0: return TCapabilitySet(ECapabilityTCB); // Filter out sub-dir names which do not have 8 bytes, i.e. do not represent a SID sl@0: sl@0: TLex hexConverter(privateSubDirName); sl@0: TUint32 foundSecureIdInt; sl@0: if (hexConverter.Val(foundSecureIdInt, EHex) != KErrNone) sl@0: return TCapabilitySet(ECapabilityTCB); // Filter out paths which do not have a subdir under private sl@0: sl@0: TSecureId foundSecureId(foundSecureIdInt); sl@0: if (foundSecureId != aClientSid) // Check whether this the client's SID sl@0: { sl@0: TPtrC nextSubPath; // Check for /private//import directories sl@0: TPtrC nextSubDir; sl@0: if (!GetNextDirNameL(remainingSubPath, nextSubDir, nextSubPath) || nextSubDir.CompareF(_L("import")) != 0) sl@0: { sl@0: // If not an import directory, require TCB or AllFiles sl@0: TCapabilitySet ret(ECapabilityTCB); sl@0: ret.AddCapability(ECapabilityAllFiles); sl@0: return ret; sl@0: } sl@0: } sl@0: sl@0: TCapabilitySet emptySet; sl@0: emptySet.SetEmpty(); sl@0: return emptySet; sl@0: } sl@0: sl@0: EXPORT_C TCapabilitySet SecCommonUtils::FileModificationRequiredCapabilitiesL(const TDesC& aFileName, TSecureId aClientSid) sl@0: { sl@0: TCapabilitySet emptySet; sl@0: emptySet.SetEmpty(); sl@0: sl@0: // TParsePtrC is unusable, since it panics on incorrect paths. We have to use TParse and create a temporary buffer for it (as there's no TParseC) sl@0: RBuf tempbuf; sl@0: tempbuf.CreateL(aFileName); sl@0: tempbuf.CleanupClosePushL(); sl@0: sl@0: TParse pathParse; sl@0: if (pathParse.Set(tempbuf, NULL, NULL) != KErrNone) sl@0: { sl@0: CleanupStack::PopAndDestroy(&tempbuf); sl@0: // Path failed to parse - require TCB, as it is the only capability which allows modification anywhere on the FS sl@0: // (and we do not know where on the FS this file is) sl@0: return TCapabilitySet(ECapabilityTCB); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(&tempbuf); sl@0: sl@0: // check for wild cards (such as * or ?) in paths sl@0: if(pathParse.IsWild()) sl@0: return TCapabilitySet(ECapabilityTCB); sl@0: sl@0: // check for relative paths sl@0: if(aFileName.Find(_L("..")) != KErrNotFound) sl@0: return TCapabilitySet(ECapabilityTCB); sl@0: sl@0: TPtrC pathTmp = pathParse.Path(); sl@0: if (pathTmp.Length() <= 1) // The should be at least one directory - otherwise there's nothing to check sl@0: return emptySet; sl@0: sl@0: // Get the first directory name sl@0: TPtrC path = pathTmp.Mid(1); // Remove the leading slash sl@0: sl@0: TPtrC firstDirName; sl@0: TPtrC remainingPath; sl@0: TBool nextDirAvailable = GetNextDirNameL(path, firstDirName, remainingPath); sl@0: __ASSERT_ALWAYS(nextDirAvailable, User::Invariant()); // There should be at least one directory if the Path() was not empty sl@0: sl@0: // For 'sys' or 'resource', require TCB sl@0: if (firstDirName.CompareF(_L("sys")) == 0 || firstDirName.CompareF(_L("resource")) == 0) sl@0: return TCapabilitySet(ECapabilityTCB); sl@0: sl@0: if (firstDirName.CompareF(_L("private")) == 0) sl@0: return PrivateModificationRequiredCapabilitiesL(remainingPath, aClientSid); sl@0: sl@0: // If the directory name is not 'private', 'resource' or 'sys', no capabilities are required sl@0: return emptySet; sl@0: }