1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sql/SRC/Server/SqlSrvAuthorizer.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,571 @@
1.4 +// Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "SqlSrvAuthorizer.h" //MSqlPolicyInspector
1.20 +#include "SqlSrvMain.h" //CSqlServer
1.21 +#include "SqlSrvSecurityMap.h" //RSqlSecurityMap
1.22 +#include "SqlSrvDatabase.h" //CSqlSrvDatabase
1.23 +#include "SqlSecurityImpl.h" //CSqlSecurityPolicy
1.24 +#include "SqlSrvDbSysSettings.h"//TSqlDbSysSettings
1.25 +#include "SqlSrvUtil.h" //Global server functions
1.26 +#include "SqlSrvStatementUtil.h"//Global sql statement related functions
1.27 +#include "SqlSrvStrings.h" //KTempDb
1.28 +#include "sqlite3.h"
1.29 +#include "SqliteSymbian.h" //sqlite3SymbianLastOsError()
1.30 +
1.31 +//This macro is used to suppress "function argument not used" compiler warning.
1.32 +#define UNUSED_ARG(arg) arg = (arg)
1.33 +
1.34 +//Array of pragma commands
1.35 +const TPtrC8 KPragmaCommands[] =
1.36 + {
1.37 + KAutoVacuum(), KCacheSize(), KCaseSensitiveLike(), KCountChanges(), KDefaultCacheSize(),
1.38 + KEmptyResultCallbacks(), KEncoding(), KFullColumnNames(), KFullfsync(), KIncrementalVacuum(),
1.39 + KJournalMode(), KJournalSizeLimit(), KLegacyFileFormat(), KLockingMode(), KPageSize(),
1.40 + KMaxPageCount(), KReadUncommitted(), KShortColumnNames(), KSynchronousFlag(), KTempStore(),
1.41 + KTempStoreDirectory(), KDatabaseList(), KForeignKeyList(), KFreelistCount(), KIndexInfo(),
1.42 + KIndexIist(), KPageCount(),KTableInfo(), KSchemaVersion(), KUserVersion(),
1.43 + KIntegrityCheck(),KParserTrace(), KVdbeTrace(), KdbeListing()
1.44 + };
1.45 +
1.46 +const TInt KMaxPragmaCommands = sizeof(KPragmaCommands) / sizeof(KPragmaCommands[0]);
1.47 +
1.48 +
1.49 +//Define the different ways of calling a pragam depending on the following
1.50 +// 1) If its a secure or non secure database
1.51 +// 2) If the pragma is called with a parameter (write) or without a parameter (read)
1.52 +struct TPragmaAccess
1.53 + {
1.54 + TInt iNonSecureRead;
1.55 + TInt iNonSecureWrite;
1.56 + TInt iSecureRead;
1.57 + TInt iSecureWrite;
1.58 + };
1.59 +
1.60 +//Table specifying the permissions for each pragma command for secure (shared) and non-secure (public and private)
1.61 +//databases. For each database permissions for the following situations are specified
1.62 +//1) With Parameter - e.g "Pragma auto_vacuum = 0"
1.63 +//2) Without Parameter - e.g "Pragma auto_vacuum"
1.64 +
1.65 +//Permissions "without parameters" usually apply to a pragma query (or read)
1.66 +//Permissions "with parameters" usually apply to pragama set (or write)
1.67 +//However please note that this is not always the case. e.g "index_info" requires a parameter but is used to query
1.68 +//(or read) the database and not a pragma set.
1.69 +const TPragmaAccess KPermissionsTable[KMaxPragmaCommands] =
1.70 + {
1.71 + /////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.72 + // NON_SECURE | SECURE |
1.73 + // W/Out Parameter |With Parameter |W/Out Parameter|With Parameter |Pragma Command
1.74 + /////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.75 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //0. auto_vacuum
1.76 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //1.cache_size
1.77 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //2.case_sensitive_like
1.78 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //3.count_changes
1.79 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //4.cache_size
1.80 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //5.empty_result_callbacks
1.81 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //6.encoding
1.82 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //7.full_column_names
1.83 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //8.fullfsync
1.84 + {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //9.incremental_vacuum
1.85 + {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //10.journal_mode
1.86 + {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //11.journal_size_limit
1.87 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //12.legacy_file_format
1.88 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //13.locking_mode
1.89 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //14.page_size
1.90 + {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //15.max_page_count
1.91 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //16.read_uncommitted
1.92 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //17.short_column_names
1.93 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //18.synchronous
1.94 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //19.temp_store
1.95 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //20.temp_store_directory
1.96 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //21.database_list
1.97 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //22.foreign_key_list
1.98 + {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //23.freelist_count
1.99 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //24.index_info
1.100 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //25.index_list
1.101 + {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //26.page_count
1.102 + {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //27.table_info
1.103 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //28.schema_version
1.104 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //29.user_version
1.105 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //30.integrity_check
1.106 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //31.parser_trace
1.107 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //32.vdbe_trace
1.108 + {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //33.vdbe_listing
1.109 + };
1.110 +
1.111 +
1.112 +//This const array describes the relation between the database operation type and
1.113 +//the number of the authorizer argument where the table name is.
1.114 +//For example:
1.115 +//- SQLITE_CREATE_TEMP_TABLE operation. The table name is in aDbObjName1 argument, so the array element value is 1.
1.116 +//- SQLITE_PRAGMA operation. No table name for this operation, so the array element value is 0.
1.117 +//- SQLITE_CREATE_TEMP_TRIGGER operation. The table name is in aDbObjName2 argument, so the array element value is 2.
1.118 +const TUint8 KTableNameArgIndex[] =
1.119 + {
1.120 + /////////////////////////////////////////////////////////////////
1.121 + // aDbObjName1 aDbObjName2
1.122 + /////////////////////////////////////////////////////////////////
1.123 + 1, //SQLITE_COPY Table Name Filename
1.124 + 2, //SQLITE_CREATE_INDEX Index Name Table Name
1.125 + 1, //SQLITE_CREATE_TABLE Table Name NULL
1.126 + 2, //SQLITE_CREATE_TEMP_INDEX Index Name Table Name
1.127 + 1, //SQLITE_CREATE_TEMP_TABLE Table Name NULL
1.128 + 2, //SQLITE_CREATE_TEMP_TRIGGER Trigger Name Table Name
1.129 + 0, //SQLITE_CREATE_TEMP_VIEW View Name NULL
1.130 + 2, //SQLITE_CREATE_TRIGGER Trigger Name Table Name
1.131 + 0, //SQLITE_CREATE_VIEW View Name NULL
1.132 + 1, //SQLITE_DELETE Table Name NULL
1.133 + 2, //SQLITE_DROP_INDEX Index Name Table Name
1.134 + 1, //SQLITE_DROP_TABLE Table Name NULL
1.135 + 2, //SQLITE_DROP_TEMP_INDEX Index Name Table Name
1.136 + 1, //SQLITE_DROP_TEMP_TABLE Table Name NULL
1.137 + 2, //SQLITE_DROP_TEMP_TRIGGER Trigger Name Table Name
1.138 + 0, //SQLITE_DROP_TEMP_VIEW View Name NULL
1.139 + 2, //SQLITE_DROP_TRIGGER Trigger Name Table Name
1.140 + 0, //SQLITE_DROP_VIEW View Name NULL
1.141 + 1, //SQLITE_INSERT Table Name NULL
1.142 + 0, //SQLITE_PRAGMA Pragma Name 1st arg or NULL
1.143 + 1, //SQLITE_READ Table Name Column Name
1.144 + 0, //SQLITE_SELECT NULL NULL
1.145 + 0, //SQLITE_TRANSACTION NULL NULL
1.146 + 1, //SQLITE_UPDATE Table Name Column Name
1.147 + 0, //SQLITE_ATTACH Filename NULL
1.148 + 0, //SQLITE_DETACH Database Name NULL
1.149 + 2, //SQLITE_ALTER_TABLE Database Name Table Name
1.150 + 0, //SQLITE_REINDEX Index Name NULL
1.151 + 1, //SQLITE_ANALYZE Table Name NULL
1.152 + 1, //SQLITE_CREATE_VTABLE Table Name Module Name
1.153 + 1, //SQLITE_DROP_VTABLE Table Name Module Name
1.154 + 0 //SQLITE_FUNCTION Function Name NULL
1.155 + };
1.156 +
1.157 +//The function returns the argument number where the table name is.
1.158 +inline TInt DbOp2TableNameArgIndex(TInt aDbOpType)
1.159 + {
1.160 + __ASSERT_DEBUG(aDbOpType > 0 && aDbOpType <= SQLITE_FUNCTION, __SQLPANIC2(ESqlPanicInternalError));
1.161 + return KTableNameArgIndex[aDbOpType];
1.162 + }
1.163 +
1.164 +//The function returns the table name, which may be in aDbObjName1 or aDbObjName2, depending on aDbOpType value.
1.165 +//The return value is "const char" pointer to a zero terminated string.
1.166 +inline const char* DbOp2TableName(TInt aDbOpType, const char* aDbObjName1, const char* aDbObjName2)
1.167 + {
1.168 + TInt pos = DbOp2TableNameArgIndex(aDbOpType);
1.169 + if(pos == 2)
1.170 + {
1.171 + __ASSERT_DEBUG(aDbObjName2 != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.172 + return aDbObjName2;
1.173 + }
1.174 + else if(pos == 1)
1.175 + {
1.176 + __ASSERT_DEBUG(aDbObjName1 != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.177 + return aDbObjName1;
1.178 + }
1.179 + return NULL;//Some database operations do not use table name
1.180 + }
1.181 +
1.182 +//This function returns the database name which may be in aDbObjName1 or aDbName depending on aDbOpType value.
1.183 +//The return value is "const char" pointer to a zero terminated string.
1.184 +inline const char* DbOp2DbName(TInt aDbOpType, const char* aDbObjName1, const char* aDbName)
1.185 + {
1.186 + if(aDbOpType == SQLITE_DETACH || aDbOpType == SQLITE_ALTER_TABLE)
1.187 + {
1.188 + __ASSERT_DEBUG(aDbObjName1 != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.189 + return aDbObjName1;
1.190 + }
1.191 + return aDbName;//It may be NULL for some database operations
1.192 + }
1.193 +
1.194 +/**
1.195 +This function performs pragma permission checks for non-secure and secure databases
1.196 +
1.197 +@param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the
1.198 + values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.199 +@param aParamUsed ETrue if the pragma command has been executed with a parameter, EFalse otherwise
1.200 +@param aSecure ETrue if the pragam check if for secure database, EFalse otherwise
1.201 +
1.202 +@return SQLITE_OK Access is allowed
1.203 +@return SQLITE_DENY The entire SQL statement should be aborted
1.204 +@return SQLITE_IGNORE The column should be treated as it has NULL value
1.205 +
1.206 +@internalComponent
1.207 + */
1.208 +static TInt PragmaCheck(const char* aDbObjName1, TBool aParamUsed, TBool aSecure)
1.209 + {
1.210 + //Retreive the pragma name
1.211 + TPtrC8 DbObjName1(KNullDesC8);
1.212 + DbObjName1.Set(reinterpret_cast <const TUint8*> (aDbObjName1));
1.213 +
1.214 + //Access the pragma permissions table depending if its :-
1.215 + // 1) Secure or non-secure database.
1.216 + // 2) Parameter was used or not.
1.217 + for (TInt index=0; index<KMaxPragmaCommands; index++)
1.218 + {
1.219 + if (CompareNoCase8(DbObjName1,KPragmaCommands[index])== 0)
1.220 + {
1.221 + if (aSecure)
1.222 + {
1.223 + if(aParamUsed)
1.224 + return KPermissionsTable[index].iSecureWrite;
1.225 + else
1.226 + return KPermissionsTable[index].iSecureRead;
1.227 + }
1.228 + else
1.229 + {
1.230 + if(aParamUsed)
1.231 + return KPermissionsTable[index].iNonSecureWrite;
1.232 + else
1.233 + return KPermissionsTable[index].iNonSecureRead;
1.234 + }
1.235 + }
1.236 + }
1.237 + //If the pragma is not on the list then deny access
1.238 + return SQLITE_DENY;
1.239 + }
1.240 +
1.241 +
1.242 +/**
1.243 +This function performs additional permission checks for non-secure (private and public) databases
1.244 +
1.245 +@param aDbOpType Database operation type, which needs to be authorized.
1.246 +@param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the
1.247 + values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.248 +@param aDbObjName2 Table or Column name. It depends on the values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.249 +
1.250 +@return SQLITE_OK Access is allowed
1.251 +@return SQLITE_DENY The entire SQL statement should be aborted
1.252 +@return SQLITE_IGNORE The column should be treated as it has NULL value
1.253 +
1.254 +@panic SqlDb 7 In _DEBUG mode. Unknown/invalid aDbOpType argument.
1.255 +
1.256 +@internalComponent
1.257 + */
1.258 +static TInt NonSecureChecks(TInt aDbOpType,const char* aDbObjName1, const char* aDbObjName2)
1.259 + {
1.260 + //=================================================================
1.261 + // aDbOpType aDbObjName1 aDbObjName2
1.262 + //=================================================================
1.263 + TInt res = SQLITE_OK;
1.264 + switch(aDbOpType)
1.265 + {
1.266 + case SQLITE_CREATE_INDEX:// Index Name Table Name
1.267 + case SQLITE_CREATE_TABLE:// Table Name NULL
1.268 + case SQLITE_CREATE_TRIGGER:// Trigger Name Table Name
1.269 + case SQLITE_CREATE_VIEW:// View Name NULL
1.270 + case SQLITE_DROP_INDEX:// Index Name Table Name
1.271 + case SQLITE_DROP_TABLE:// Table Name NULL
1.272 + case SQLITE_DROP_TRIGGER:// Trigger Name Table Name
1.273 + case SQLITE_DROP_VIEW:// View Name NULL
1.274 + case SQLITE_ALTER_TABLE:// Database Name Table Name
1.275 + case SQLITE_SELECT:// NULL NULL
1.276 + case SQLITE_TRANSACTION:// NULL NULL
1.277 + case SQLITE_DELETE:// Table Name NULL
1.278 + case SQLITE_INSERT:// Table Name NULL
1.279 + case SQLITE_UPDATE:// Table Name Column Name
1.280 + case SQLITE_READ:// Table Name Column Name
1.281 + case SQLITE_ATTACH:// Filename NULL
1.282 + case SQLITE_DETACH:// Database Name NULL
1.283 + case SQLITE_REINDEX:// Index Name NULL
1.284 + case SQLITE_ANALYZE:// Table Name NULL
1.285 + case SQLITE_FUNCTION:
1.286 + break;
1.287 + case SQLITE_PRAGMA:// Pragma Name 1st arg or NULL
1.288 + res = PragmaCheck(aDbObjName1, (aDbObjName2 != NULL), EFalse);
1.289 + break;
1.290 +//All "temp" operations are handled earlier, in CSqlSrvDatabase::AuthorizeCallback(), where a check for "temp"
1.291 +//database name is performed.
1.292 +// case SQLITE_CREATE_TEMP_INDEX:// Index Name Table Name
1.293 +// case SQLITE_CREATE_TEMP_TABLE:// Table Name NULL
1.294 +// case SQLITE_CREATE_TEMP_TRIGGER:// Trigger Name Table Name
1.295 +// case SQLITE_CREATE_TEMP_VIEW:// View Name NULL
1.296 +// case SQLITE_DROP_TEMP_INDEX:// Index Name Table Name
1.297 +// case SQLITE_DROP_TEMP_TABLE:// Table Name NULL
1.298 +// case SQLITE_DROP_TEMP_TRIGGER:// Trigger Name Table Name
1.299 +// case SQLITE_DROP_TEMP_VIEW:// View Name NULL
1.300 +//"CREATE VIRTUAL TABLE" and "DROP VIRTUAL TABLE" sql statements are not supported
1.301 +// case SQLITE_CREATE_VTABLE:
1.302 +// case SQLITE_DROP_VTABLE:
1.303 + default:
1.304 + __ASSERT_DEBUG(EFalse, __SQLPANIC2(ESqlPanicInternalError));
1.305 + break;
1.306 + }
1.307 + return res;
1.308 + }
1.309 +
1.310 +/**
1.311 +This function performs additional permission checks for secure databases
1.312 +
1.313 +@param aSecurityPolicy Security policy corresponding to this database
1.314 +@param aDbOpType Database operation type, which needs to be authorized.
1.315 +@param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the
1.316 + values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.317 +@param aDbObjName2 Table or Column name. It depends on the values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.318 +
1.319 +@return SQLITE_OK Access is allowed
1.320 +@return SQLITE_DENY The entire SQL statement should be aborted
1.321 +@return SQLITE_IGNORE The column should be treated as it has NULL value
1.322 +
1.323 +@panic SqlDb 7 In _DEBUG mode. Unknown/invalid aDbOpType argument.
1.324 +
1.325 +@internalComponent
1.326 + */
1.327 +static TInt SecureChecks(const CSqlSecurityPolicy* aSecurityPolicy,TInt aDbOpType,const char* aDbObjName1, const char* aDbObjName2)
1.328 + {
1.329 + TPtrC8 tblName(KNullDesC8);
1.330 + const char* tblNamePtr = DbOp2TableName(aDbOpType, aDbObjName1, aDbObjName2);
1.331 + if(tblNamePtr)
1.332 + {
1.333 + tblName.Set(reinterpret_cast <const TUint8*> (tblNamePtr));
1.334 + }
1.335 +
1.336 + //Under no circumstances is allowed to do any operation with the system tables.
1.337 + //(Even SQLITE_READ operation, because the system tables data is read at the moment when the database
1.338 + // is created/opened)
1.339 + if(::IsSystemTableName(tblName))
1.340 + {
1.341 + return SQLITE_DENY;
1.342 + }
1.343 + //=================================================================
1.344 + // aDbOpType aDbObjName1 aDbObjName2
1.345 + //=================================================================
1.346 + MSqlPolicyInspector& inspector = ::SqlServer().SecurityInspector();
1.347 + TSecurityPolicy schemaPolicy = aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::ESchemaPolicy);
1.348 + TSecurityPolicy writePolicy = aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::EWritePolicy);
1.349 + TSecurityPolicy readPolicy = aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::EReadPolicy);
1.350 + TInt res = SQLITE_OK;
1.351 + switch(aDbOpType)
1.352 + {
1.353 + //"Database schema policy" check
1.354 + case SQLITE_CREATE_INDEX:// Index Name Table Name
1.355 + case SQLITE_CREATE_TABLE:// Table Name NULL
1.356 + case SQLITE_CREATE_TRIGGER:// Trigger Name Table Name
1.357 + case SQLITE_CREATE_VIEW:// View Name NULL
1.358 + case SQLITE_DROP_INDEX:// Index Name Table Name
1.359 + case SQLITE_DROP_TABLE:// Table Name NULL
1.360 + case SQLITE_DROP_TRIGGER:// Trigger Name Table Name
1.361 + case SQLITE_DROP_VIEW:// View Name NULL
1.362 + case SQLITE_ALTER_TABLE:// Database Name Table Name
1.363 + if(!inspector.Check(schemaPolicy))
1.364 + {
1.365 + res = SQLITE_DENY;
1.366 + }
1.367 + break;
1.368 + //No policy check
1.369 + case SQLITE_SELECT:// NULL NULL
1.370 + case SQLITE_TRANSACTION:// NULL NULL
1.371 + break;
1.372 + //"Database schema policy" for sqlite tables
1.373 + //"Database schema policy" || "Database write policy" for user tables
1.374 + case SQLITE_DELETE:// Table Name NULL
1.375 + case SQLITE_INSERT:// Table Name NULL
1.376 + case SQLITE_UPDATE:// Table Name Column Name
1.377 + if(!inspector.Check(schemaPolicy))
1.378 + {
1.379 + res = SQLITE_DENY;
1.380 + if(!::IsSqliteTableName(tblName))
1.381 + {
1.382 + if(inspector.Check(writePolicy))
1.383 + {
1.384 + res = SQLITE_OK;
1.385 + }
1.386 + }
1.387 + }
1.388 + break;
1.389 + //"Database schema policy" || "Database read policy" || "Database write policy" for sqlite tables
1.390 + //"Database schema policy" || "Database read policy" for user tables
1.391 + case SQLITE_READ:// Table Name Column Name
1.392 + if(!(inspector.Check(schemaPolicy) || inspector.Check(readPolicy)))
1.393 + {
1.394 + res = SQLITE_DENY;
1.395 + if(::IsSqliteTableName(tblName))
1.396 + {
1.397 + if(inspector.Check(writePolicy))
1.398 + {
1.399 + res = SQLITE_OK;
1.400 + }
1.401 + }
1.402 + }
1.403 + break;
1.404 + case SQLITE_PRAGMA:// Pragma Name 1st arg or NULL
1.405 + res = PragmaCheck(aDbObjName1, (aDbObjName2 != NULL), ETrue);
1.406 + break;
1.407 + case SQLITE_ATTACH:// Filename NULL
1.408 + case SQLITE_DETACH:// Database Name NULL
1.409 + //If the operation is SQLITE_ATTACH or SQLITE_DETACH, return SQLITE_DENY.
1.410 + //"ATTACH DATABASE"/"DETACH DATABASE" operations are performed by separate "attach/detach db" methods.
1.411 + res = SQLITE_DENY;
1.412 + break;
1.413 + //No policy check
1.414 + case SQLITE_REINDEX:// Index Name NULL
1.415 + case SQLITE_ANALYZE:// Table Name NULL
1.416 + break;
1.417 + //No policy check
1.418 + case SQLITE_FUNCTION:
1.419 + break;
1.420 +//All "temp" operations are handled earlier, in CSqlSrvDatabase::AuthorizeCallback(), where a check for "temp"
1.421 +//database name is performed.
1.422 +// case SQLITE_CREATE_TEMP_INDEX:// Index Name Table Name
1.423 +// case SQLITE_CREATE_TEMP_TABLE:// Table Name NULL
1.424 +// case SQLITE_CREATE_TEMP_TRIGGER:// Trigger Name Table Name
1.425 +// case SQLITE_CREATE_TEMP_VIEW:// View Name NULL
1.426 +// case SQLITE_DROP_TEMP_INDEX:// Index Name Table Name
1.427 +// case SQLITE_DROP_TEMP_TABLE:// Table Name NULL
1.428 +// case SQLITE_DROP_TEMP_TRIGGER:// Trigger Name Table Name
1.429 +// case SQLITE_DROP_TEMP_VIEW:// View Name NULL
1.430 +//"CREATE VIRTUAL TABLE" and "DROP VIRTUAL TABLE" sql statements are not supported
1.431 +// case SQLITE_CREATE_VTABLE:
1.432 +// case SQLITE_DROP_VTABLE:
1.433 + default:
1.434 + __ASSERT_DEBUG(EFalse, __SQLPANIC2(ESqlPanicInternalError));
1.435 + break;
1.436 + }
1.437 + return res;
1.438 + }
1.439 +
1.440 +/**
1.441 +This callback function is invoked by the SQLITE engine at SQL statement compile time
1.442 +for each attempt to access a column of a table in the database.
1.443 +
1.444 +The callback returns SQLITE_OK if access is allowed,
1.445 +SQLITE_DENY if the entire SQL statement should be aborted with an error and
1.446 +SQLITE_IGNORE if the column should be treated as a NULL value.
1.447 +
1.448 +@param aDb "This" pointer (to the rellated CSqlSrvDatabase object).
1.449 +@param aDbOpType Database operation type, which needs to be authorized. It could be one of these:
1.450 +
1.451 +@code
1.452 +=================================================================
1.453 +aDbOpType aDbObjName1 aDbObjName2
1.454 +=================================================================
1.455 +SQLITE_CREATE_INDEX Index Name Table Name
1.456 +SQLITE_CREATE_TABLE Table Name NULL
1.457 +SQLITE_CREATE_TEMP_INDEX Index Name Table Name
1.458 +SQLITE_CREATE_TEMP_TABLE Table Name NULL
1.459 +SQLITE_CREATE_TEMP_TRIGGER Trigger Name Table Name
1.460 +SQLITE_CREATE_TEMP_VIEW View Name NULL
1.461 +SQLITE_CREATE_TRIGGER Trigger Name Table Name
1.462 +SQLITE_CREATE_VIEW View Name NULL
1.463 +SQLITE_DELETE Table Name NULL
1.464 +SQLITE_DROP_INDEX Index Name Table Name
1.465 +SQLITE_DROP_TABLE Table Name NULL
1.466 +SQLITE_DROP_TEMP_INDEX Index Name Table Name
1.467 +SQLITE_DROP_TEMP_TABLE Table Name NULL
1.468 +SQLITE_DROP_TEMP_TRIGGER Trigger Name Table Name
1.469 +SQLITE_DROP_TEMP_VIEW View Name NULL
1.470 +SQLITE_DROP_TRIGGER Trigger Name Table Name
1.471 +SQLITE_DROP_VIEW View Name NULL
1.472 +SQLITE_INSERT Table Name NULL
1.473 +SQLITE_PRAGMA Pragma Name 1st arg or NULL
1.474 +SQLITE_READ Table Name Column Name
1.475 +SQLITE_SELECT NULL NULL
1.476 +SQLITE_TRANSACTION NULL NULL
1.477 +SQLITE_UPDATE Table Name Column Name
1.478 +SQLITE_ATTACH Filename NULL
1.479 +SQLITE_DETACH Database Name NULL
1.480 +SQLITE_ALTER_TABLE Database Name Table Name
1.481 +SQLITE_REINDEX Index Name NULL
1.482 +SQLITE_ANALYZE Table Name NULL
1.483 +SQLITE_CREATE_VTABLE Table Name Module Name
1.484 +SQLITE_DROP_VTABLE Table Name Module Name
1.485 +SQLITE_FUNCTION Function Name NULL
1.486 +=================================================================
1.487 +@endcode
1.488 +
1.489 +@param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the
1.490 + values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.491 +@param aDbObjName2 Table or Column name. It depends on the values of aDbOpType argument. UTF8 encoded, zero-terminated.
1.492 +@param aDbName Database name - "main", "temp", etc. UTF8 encoded, zero-terminated.
1.493 +@param aTrgOrViewName The name of the inner-most trigger or view that is responsible for the access
1.494 + attempt or NULL if this access attempt is directly from input SQL code. UTF8 encoded, zero-terminated.
1.495 +
1.496 +@return SQLITE_OK Access is allowed
1.497 +@return SQLITE_DENY The entire SQL statement should be aborted
1.498 +@return SQLITE_IGNORE The column should be treated as it has NULL value
1.499 +
1.500 +@panic SqlDb 4 In _DEBUG mode. The authorizer was called with NULL aDb argument.
1.501 +
1.502 +@internalComponent
1.503 +*/
1.504 +TInt CSqlSrvDatabase::AuthorizeCallback(void* aDb, TInt aDbOpType,
1.505 + const char* aDbObjName1, const char* aDbObjName2,
1.506 + const char* aDbName, const char* aTrgOrViewName)
1.507 + {
1.508 + UNUSED_ARG(aTrgOrViewName);
1.509 + __ASSERT_DEBUG(aDb != NULL, __SQLPANIC2(ESqlPanicBadArgument));
1.510 +
1.511 +#ifdef _SQL_AUTHORIZER_TRACE_ENABLED
1.512 + enum TDbOpType {EOpCreateIndex = 1, EOpCreateTable, EOpCreateTempIndex, EOpCreateTempTable,
1.513 + EOpCreateTempTrigger, EOpCreateTempView, EOpCreateTrigger, EOpCreateView, EOpDelete, EOpDropIndex,
1.514 + EOpDropTable, EOpDropTempIndex, EOpDropTempTable, EOpDropTempTrigger, EOpDropTempView, EOpDropTrigger,
1.515 + EOpDropView, EOpInsert, EOpPragma, EOpRead, EOpSelect, EOpTransaction, EOpUpdate, EOpAttach, EOpDettach,
1.516 + EOpAlterTable, EOpReindex, EOpAnalyze, EOpCreateVTable, EOpDropVTable, EOpFunctionCall};
1.517 + TDbOpType dbOpType = static_cast <TDbOpType> (aDbOpType);//can be seen now in the debugger
1.518 + ::PrintAuthorizerArguments(dbOpType, aDbObjName1, aDbObjName2, aDbName, aTrgOrViewName);
1.519 +#endif
1.520 +
1.521 + CSqlSrvDatabase& db = *static_cast <CSqlSrvDatabase*> (aDb);
1.522 +
1.523 + //1. If the authorizer is currently disabled - return SQLITE_OK.
1.524 + // (This happens when a database is attached/detached)
1.525 + if(db.iAuthorizerDisabled)
1.526 + {
1.527 + return SQLITE_OK;
1.528 + }
1.529 +
1.530 + TPtrC8 dbName(KNullDesC8);
1.531 + const char* dbNamePtr = DbOp2DbName(aDbOpType, aDbObjName1, aDbName);//dbNamePtr is zero terminated
1.532 + if(dbNamePtr)
1.533 + {
1.534 + dbName.Set(reinterpret_cast <const TUint8*> (dbNamePtr));
1.535 + }
1.536 + aDbName = NULL;//No more use of aDbName argument inside the function.
1.537 +
1.538 + //2. If the database name is KTempDb, then allow the access. It is a local database
1.539 + // (for the client), deleted when closed.
1.540 + if(dbName.Compare(KTempDb8) == 0) //dbName is guaranteed to be in lower case if it is "temp",
1.541 + { //so it is possible to use binary string comparison
1.542 + return SQLITE_OK;
1.543 + }
1.544 +
1.545 + //3. Find the security policies. For DefaultAccess initialized with NULL.
1.546 + const CSqlSecurityPolicy* securityPolicy = NULL;
1.547 + if(dbName.Compare(KMainDb8) == 0||dbName.Length() == 0) //dbName is guaranteed to be in lower case if it is "main",
1.548 + { //so it is possible to use binary string comparison
1.549 + //4. This is the main database.
1.550 + securityPolicy = db.iSecurityPolicy;
1.551 + }
1.552 + else
1.553 + {
1.554 + //5. This is an attached database. Find the attached database security policies.
1.555 + //dbNamePtr is used here because it is zero terminated
1.556 + TSqlAttachDbPair* attachDbPair = db.iAttachDbMap.Entry(reinterpret_cast <const TUint8*> (dbNamePtr));
1.557 + if(attachDbPair)
1.558 + {//secure database, find the security policies
1.559 + const TUint8* securityMapKey = attachDbPair->iData;
1.560 + RSqlSecurityMap& map = ::SqlServer().SecurityMap();
1.561 + TSqlSecurityPair* pair = map.Entry(securityMapKey);
1.562 + if(pair)
1.563 + {
1.564 + securityPolicy = pair->iData;
1.565 + }
1.566 + }
1.567 + }
1.568 +
1.569 + //Here we have:
1.570 + // - valid database name (not NULL);
1.571 +
1.572 + //6. Default or Security Policy Checks
1.573 + return !securityPolicy ? NonSecureChecks(aDbOpType,aDbObjName1,aDbObjName2): SecureChecks(securityPolicy,aDbOpType,aDbObjName1,aDbObjName2);
1.574 + }