|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "SqlSrvAuthorizer.h" //MSqlPolicyInspector |
|
17 #include "SqlSrvMain.h" //CSqlServer |
|
18 #include "SqlSrvSecurityMap.h" //RSqlSecurityMap |
|
19 #include "SqlSrvDatabase.h" //CSqlSrvDatabase |
|
20 #include "SqlSecurityImpl.h" //CSqlSecurityPolicy |
|
21 #include "SqlSrvDbSysSettings.h"//TSqlDbSysSettings |
|
22 #include "SqlSrvUtil.h" //Global server functions |
|
23 #include "SqlSrvStatementUtil.h"//Global sql statement related functions |
|
24 #include "SqlSrvStrings.h" //KTempDb |
|
25 #include "sqlite3.h" |
|
26 #include "SqliteSymbian.h" //sqlite3SymbianLastOsError() |
|
27 |
|
28 //This macro is used to suppress "function argument not used" compiler warning. |
|
29 #define UNUSED_ARG(arg) arg = (arg) |
|
30 |
|
31 //Array of pragma commands |
|
32 const TPtrC8 KPragmaCommands[] = |
|
33 { |
|
34 KAutoVacuum(), KCacheSize(), KCaseSensitiveLike(), KCountChanges(), KDefaultCacheSize(), |
|
35 KEmptyResultCallbacks(), KEncoding(), KFullColumnNames(), KFullfsync(), KIncrementalVacuum(), |
|
36 KJournalMode(), KJournalSizeLimit(), KLegacyFileFormat(), KLockingMode(), KPageSize(), |
|
37 KMaxPageCount(), KReadUncommitted(), KShortColumnNames(), KSynchronousFlag(), KTempStore(), |
|
38 KTempStoreDirectory(), KDatabaseList(), KForeignKeyList(), KFreelistCount(), KIndexInfo(), |
|
39 KIndexIist(), KPageCount(),KTableInfo(), KSchemaVersion(), KUserVersion(), |
|
40 KIntegrityCheck(),KParserTrace(), KVdbeTrace(), KdbeListing() |
|
41 }; |
|
42 |
|
43 const TInt KMaxPragmaCommands = sizeof(KPragmaCommands) / sizeof(KPragmaCommands[0]); |
|
44 |
|
45 |
|
46 //Define the different ways of calling a pragam depending on the following |
|
47 // 1) If its a secure or non secure database |
|
48 // 2) If the pragma is called with a parameter (write) or without a parameter (read) |
|
49 struct TPragmaAccess |
|
50 { |
|
51 TInt iNonSecureRead; |
|
52 TInt iNonSecureWrite; |
|
53 TInt iSecureRead; |
|
54 TInt iSecureWrite; |
|
55 }; |
|
56 |
|
57 //Table specifying the permissions for each pragma command for secure (shared) and non-secure (public and private) |
|
58 //databases. For each database permissions for the following situations are specified |
|
59 //1) With Parameter - e.g "Pragma auto_vacuum = 0" |
|
60 //2) Without Parameter - e.g "Pragma auto_vacuum" |
|
61 |
|
62 //Permissions "without parameters" usually apply to a pragma query (or read) |
|
63 //Permissions "with parameters" usually apply to pragama set (or write) |
|
64 //However please note that this is not always the case. e.g "index_info" requires a parameter but is used to query |
|
65 //(or read) the database and not a pragma set. |
|
66 const TPragmaAccess KPermissionsTable[KMaxPragmaCommands] = |
|
67 { |
|
68 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
69 // NON_SECURE | SECURE | |
|
70 // W/Out Parameter |With Parameter |W/Out Parameter|With Parameter |Pragma Command |
|
71 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
72 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //0. auto_vacuum |
|
73 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //1.cache_size |
|
74 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //2.case_sensitive_like |
|
75 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //3.count_changes |
|
76 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //4.cache_size |
|
77 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //5.empty_result_callbacks |
|
78 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //6.encoding |
|
79 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //7.full_column_names |
|
80 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //8.fullfsync |
|
81 {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //9.incremental_vacuum |
|
82 {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //10.journal_mode |
|
83 {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //11.journal_size_limit |
|
84 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //12.legacy_file_format |
|
85 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //13.locking_mode |
|
86 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //14.page_size |
|
87 {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //15.max_page_count |
|
88 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //16.read_uncommitted |
|
89 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //17.short_column_names |
|
90 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //18.synchronous |
|
91 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //19.temp_store |
|
92 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //20.temp_store_directory |
|
93 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //21.database_list |
|
94 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //22.foreign_key_list |
|
95 {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //23.freelist_count |
|
96 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //24.index_info |
|
97 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //25.index_list |
|
98 {SQLITE_IGNORE, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //26.page_count |
|
99 {SQLITE_OK, SQLITE_OK, SQLITE_DENY, SQLITE_DENY}, //27.table_info |
|
100 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //28.schema_version |
|
101 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //29.user_version |
|
102 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //30.integrity_check |
|
103 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //31.parser_trace |
|
104 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //32.vdbe_trace |
|
105 {SQLITE_OK, SQLITE_IGNORE, SQLITE_DENY, SQLITE_DENY}, //33.vdbe_listing |
|
106 }; |
|
107 |
|
108 |
|
109 //This const array describes the relation between the database operation type and |
|
110 //the number of the authorizer argument where the table name is. |
|
111 //For example: |
|
112 //- SQLITE_CREATE_TEMP_TABLE operation. The table name is in aDbObjName1 argument, so the array element value is 1. |
|
113 //- SQLITE_PRAGMA operation. No table name for this operation, so the array element value is 0. |
|
114 //- SQLITE_CREATE_TEMP_TRIGGER operation. The table name is in aDbObjName2 argument, so the array element value is 2. |
|
115 const TUint8 KTableNameArgIndex[] = |
|
116 { |
|
117 ///////////////////////////////////////////////////////////////// |
|
118 // aDbObjName1 aDbObjName2 |
|
119 ///////////////////////////////////////////////////////////////// |
|
120 1, //SQLITE_COPY Table Name Filename |
|
121 2, //SQLITE_CREATE_INDEX Index Name Table Name |
|
122 1, //SQLITE_CREATE_TABLE Table Name NULL |
|
123 2, //SQLITE_CREATE_TEMP_INDEX Index Name Table Name |
|
124 1, //SQLITE_CREATE_TEMP_TABLE Table Name NULL |
|
125 2, //SQLITE_CREATE_TEMP_TRIGGER Trigger Name Table Name |
|
126 0, //SQLITE_CREATE_TEMP_VIEW View Name NULL |
|
127 2, //SQLITE_CREATE_TRIGGER Trigger Name Table Name |
|
128 0, //SQLITE_CREATE_VIEW View Name NULL |
|
129 1, //SQLITE_DELETE Table Name NULL |
|
130 2, //SQLITE_DROP_INDEX Index Name Table Name |
|
131 1, //SQLITE_DROP_TABLE Table Name NULL |
|
132 2, //SQLITE_DROP_TEMP_INDEX Index Name Table Name |
|
133 1, //SQLITE_DROP_TEMP_TABLE Table Name NULL |
|
134 2, //SQLITE_DROP_TEMP_TRIGGER Trigger Name Table Name |
|
135 0, //SQLITE_DROP_TEMP_VIEW View Name NULL |
|
136 2, //SQLITE_DROP_TRIGGER Trigger Name Table Name |
|
137 0, //SQLITE_DROP_VIEW View Name NULL |
|
138 1, //SQLITE_INSERT Table Name NULL |
|
139 0, //SQLITE_PRAGMA Pragma Name 1st arg or NULL |
|
140 1, //SQLITE_READ Table Name Column Name |
|
141 0, //SQLITE_SELECT NULL NULL |
|
142 0, //SQLITE_TRANSACTION NULL NULL |
|
143 1, //SQLITE_UPDATE Table Name Column Name |
|
144 0, //SQLITE_ATTACH Filename NULL |
|
145 0, //SQLITE_DETACH Database Name NULL |
|
146 2, //SQLITE_ALTER_TABLE Database Name Table Name |
|
147 0, //SQLITE_REINDEX Index Name NULL |
|
148 1, //SQLITE_ANALYZE Table Name NULL |
|
149 1, //SQLITE_CREATE_VTABLE Table Name Module Name |
|
150 1, //SQLITE_DROP_VTABLE Table Name Module Name |
|
151 0 //SQLITE_FUNCTION Function Name NULL |
|
152 }; |
|
153 |
|
154 //The function returns the argument number where the table name is. |
|
155 inline TInt DbOp2TableNameArgIndex(TInt aDbOpType) |
|
156 { |
|
157 __SQLASSERT(aDbOpType > 0 && aDbOpType <= SQLITE_FUNCTION, ESqlPanicInternalError); |
|
158 return KTableNameArgIndex[aDbOpType]; |
|
159 } |
|
160 |
|
161 //The function returns the table name, which may be in aDbObjName1 or aDbObjName2, depending on aDbOpType value. |
|
162 //The return value is "const char" pointer to a zero terminated string. |
|
163 inline const char* DbOp2TableName(TInt aDbOpType, const char* aDbObjName1, const char* aDbObjName2) |
|
164 { |
|
165 TInt pos = DbOp2TableNameArgIndex(aDbOpType); |
|
166 if(pos == 2) |
|
167 { |
|
168 __SQLASSERT(aDbObjName2 != NULL, ESqlPanicInternalError); |
|
169 return aDbObjName2; |
|
170 } |
|
171 else if(pos == 1) |
|
172 { |
|
173 __SQLASSERT(aDbObjName1 != NULL, ESqlPanicInternalError); |
|
174 return aDbObjName1; |
|
175 } |
|
176 return NULL;//Some database operations do not use table name |
|
177 } |
|
178 |
|
179 //This function returns the database name which may be in aDbObjName1 or aDbName depending on aDbOpType value. |
|
180 //The return value is "const char" pointer to a zero terminated string. |
|
181 inline const char* DbOp2DbName(TInt aDbOpType, const char* aDbObjName1, const char* aDbName) |
|
182 { |
|
183 if(aDbOpType == SQLITE_DETACH || aDbOpType == SQLITE_ALTER_TABLE) |
|
184 { |
|
185 __SQLASSERT(aDbObjName1 != NULL, ESqlPanicInternalError); |
|
186 return aDbObjName1; |
|
187 } |
|
188 return aDbName;//It may be NULL for some database operations |
|
189 } |
|
190 |
|
191 /** |
|
192 This function performs pragma permission checks for non-secure and secure databases |
|
193 |
|
194 @param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the |
|
195 values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
196 @param aParamUsed ETrue if the pragma command has been executed with a parameter, EFalse otherwise |
|
197 @param aSecure ETrue if the pragam check if for secure database, EFalse otherwise |
|
198 |
|
199 @return SQLITE_OK Access is allowed |
|
200 @return SQLITE_DENY The entire SQL statement should be aborted |
|
201 @return SQLITE_IGNORE The column should be treated as it has NULL value |
|
202 |
|
203 @internalComponent |
|
204 */ |
|
205 static TInt PragmaCheck(const char* aDbObjName1, TBool aParamUsed, TBool aSecure) |
|
206 { |
|
207 //Retreive the pragma name |
|
208 TPtrC8 DbObjName1(KNullDesC8); |
|
209 DbObjName1.Set(reinterpret_cast <const TUint8*> (aDbObjName1)); |
|
210 |
|
211 //Access the pragma permissions table depending if its :- |
|
212 // 1) Secure or non-secure database. |
|
213 // 2) Parameter was used or not. |
|
214 for (TInt index=0; index<KMaxPragmaCommands; index++) |
|
215 { |
|
216 if (CompareNoCase8(DbObjName1,KPragmaCommands[index])== 0) |
|
217 { |
|
218 if (aSecure) |
|
219 { |
|
220 if(aParamUsed) |
|
221 return KPermissionsTable[index].iSecureWrite; |
|
222 else |
|
223 return KPermissionsTable[index].iSecureRead; |
|
224 } |
|
225 else |
|
226 { |
|
227 if(aParamUsed) |
|
228 return KPermissionsTable[index].iNonSecureWrite; |
|
229 else |
|
230 return KPermissionsTable[index].iNonSecureRead; |
|
231 } |
|
232 } |
|
233 } |
|
234 //If the pragma is not on the list then deny access |
|
235 return SQLITE_DENY; |
|
236 } |
|
237 |
|
238 |
|
239 /** |
|
240 This function performs additional permission checks for non-secure (private and public) databases |
|
241 |
|
242 @param aDbOpType Database operation type, which needs to be authorized. |
|
243 @param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the |
|
244 values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
245 @param aDbObjName2 Table or Column name. It depends on the values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
246 |
|
247 @return SQLITE_OK Access is allowed |
|
248 @return SQLITE_DENY The entire SQL statement should be aborted |
|
249 @return SQLITE_IGNORE The column should be treated as it has NULL value |
|
250 |
|
251 @panic SqlDb 7 In _DEBUG mode. Unknown/invalid aDbOpType argument. |
|
252 |
|
253 @internalComponent |
|
254 */ |
|
255 static TInt NonSecureChecks(TInt aDbOpType,const char* aDbObjName1, const char* aDbObjName2) |
|
256 { |
|
257 //================================================================= |
|
258 // aDbOpType aDbObjName1 aDbObjName2 |
|
259 //================================================================= |
|
260 TInt res = SQLITE_OK; |
|
261 switch(aDbOpType) |
|
262 { |
|
263 case SQLITE_CREATE_INDEX:// Index Name Table Name |
|
264 case SQLITE_CREATE_TABLE:// Table Name NULL |
|
265 case SQLITE_CREATE_TRIGGER:// Trigger Name Table Name |
|
266 case SQLITE_CREATE_VIEW:// View Name NULL |
|
267 case SQLITE_DROP_INDEX:// Index Name Table Name |
|
268 case SQLITE_DROP_TABLE:// Table Name NULL |
|
269 case SQLITE_DROP_TRIGGER:// Trigger Name Table Name |
|
270 case SQLITE_DROP_VIEW:// View Name NULL |
|
271 case SQLITE_ALTER_TABLE:// Database Name Table Name |
|
272 case SQLITE_CREATE_TEMP_INDEX:// Index Name Table Name |
|
273 case SQLITE_CREATE_TEMP_TABLE:// Table Name NULL |
|
274 case SQLITE_CREATE_TEMP_TRIGGER:// Trigger Name Table Name |
|
275 case SQLITE_CREATE_TEMP_VIEW:// View Name NULL |
|
276 case SQLITE_DROP_TEMP_INDEX:// Index Name Table Name |
|
277 case SQLITE_DROP_TEMP_TABLE:// Table Name NULL |
|
278 case SQLITE_DROP_TEMP_TRIGGER:// Trigger Name Table Name |
|
279 case SQLITE_DROP_TEMP_VIEW:// View Name NULL |
|
280 case SQLITE_SELECT:// NULL NULL |
|
281 case SQLITE_TRANSACTION:// NULL NULL |
|
282 case SQLITE_DELETE:// Table Name NULL |
|
283 case SQLITE_INSERT:// Table Name NULL |
|
284 case SQLITE_UPDATE:// Table Name Column Name |
|
285 case SQLITE_READ:// Table Name Column Name |
|
286 case SQLITE_ATTACH:// Filename NULL |
|
287 case SQLITE_DETACH:// Database Name NULL |
|
288 case SQLITE_REINDEX:// Index Name NULL |
|
289 case SQLITE_ANALYZE:// Table Name NULL |
|
290 case SQLITE_CREATE_VTABLE: |
|
291 case SQLITE_DROP_VTABLE: |
|
292 case SQLITE_FUNCTION: |
|
293 break; |
|
294 case SQLITE_PRAGMA:// Pragma Name 1st arg or NULL |
|
295 res = PragmaCheck(aDbObjName1, (aDbObjName2 != NULL), EFalse); |
|
296 break; |
|
297 default: |
|
298 __SQLASSERT(EFalse, ESqlPanicInternalError); |
|
299 break; |
|
300 } |
|
301 return res; |
|
302 } |
|
303 |
|
304 /** |
|
305 This function performs additional permission checks for secure databases |
|
306 |
|
307 @param aSecurityPolicy Security policy corresponding to this database |
|
308 @param aDbOpType Database operation type, which needs to be authorized. |
|
309 @param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the |
|
310 values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
311 @param aDbObjName2 Table or Column name. It depends on the values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
312 |
|
313 @return SQLITE_OK Access is allowed |
|
314 @return SQLITE_DENY The entire SQL statement should be aborted |
|
315 @return SQLITE_IGNORE The column should be treated as it has NULL value |
|
316 |
|
317 @panic SqlDb 7 In _DEBUG mode. Unknown/invalid aDbOpType argument. |
|
318 |
|
319 @internalComponent |
|
320 */ |
|
321 static TInt SecureChecks(const CSqlSecurityPolicy* aSecurityPolicy,TInt aDbOpType,const char* aDbObjName1, const char* aDbObjName2) |
|
322 { |
|
323 TPtrC8 tblName(KNullDesC8); |
|
324 const char* tblNamePtr = DbOp2TableName(aDbOpType, aDbObjName1, aDbObjName2); |
|
325 if(tblNamePtr) |
|
326 { |
|
327 tblName.Set(reinterpret_cast <const TUint8*> (tblNamePtr)); |
|
328 } |
|
329 |
|
330 //Under no circumstances is allowed to do any operation with the system tables. |
|
331 //(Even SQLITE_READ operation, because the system tables data is read at the moment when the database |
|
332 // is created/opened) |
|
333 if(::IsSystemTableName(tblName)) |
|
334 { |
|
335 return SQLITE_DENY; |
|
336 } |
|
337 //================================================================= |
|
338 // aDbOpType aDbObjName1 aDbObjName2 |
|
339 //================================================================= |
|
340 MSqlPolicyInspector& inspector = ::SqlServer().SecurityInspector(); |
|
341 TSecurityPolicy schemaPolicy = aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::ESchemaPolicy); |
|
342 TSecurityPolicy writePolicy = aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::EWritePolicy); |
|
343 TSecurityPolicy readPolicy = aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::EReadPolicy); |
|
344 TInt res = SQLITE_OK; |
|
345 switch(aDbOpType) |
|
346 { |
|
347 //"Database schema policy" check |
|
348 case SQLITE_CREATE_INDEX:// Index Name Table Name |
|
349 case SQLITE_CREATE_TABLE:// Table Name NULL |
|
350 case SQLITE_CREATE_TRIGGER:// Trigger Name Table Name |
|
351 case SQLITE_CREATE_VIEW:// View Name NULL |
|
352 case SQLITE_DROP_INDEX:// Index Name Table Name |
|
353 case SQLITE_DROP_TABLE:// Table Name NULL |
|
354 case SQLITE_DROP_TRIGGER:// Trigger Name Table Name |
|
355 case SQLITE_DROP_VIEW:// View Name NULL |
|
356 case SQLITE_ALTER_TABLE:// Database Name Table Name |
|
357 if(!inspector.Check(schemaPolicy)) |
|
358 { |
|
359 res = SQLITE_DENY; |
|
360 } |
|
361 break; |
|
362 //No policy check |
|
363 case SQLITE_CREATE_TEMP_INDEX:// Index Name Table Name |
|
364 case SQLITE_CREATE_TEMP_TABLE:// Table Name NULL |
|
365 case SQLITE_CREATE_TEMP_TRIGGER:// Trigger Name Table Name |
|
366 case SQLITE_CREATE_TEMP_VIEW:// View Name NULL |
|
367 case SQLITE_DROP_TEMP_INDEX:// Index Name Table Name |
|
368 case SQLITE_DROP_TEMP_TABLE:// Table Name NULL |
|
369 case SQLITE_DROP_TEMP_TRIGGER:// Trigger Name Table Name |
|
370 case SQLITE_DROP_TEMP_VIEW:// View Name NULL |
|
371 case SQLITE_SELECT:// NULL NULL |
|
372 case SQLITE_TRANSACTION:// NULL NULL |
|
373 break; |
|
374 //"Database schema policy" for sqlite tables |
|
375 //"Database schema policy" || "Database write policy" for user tables |
|
376 case SQLITE_DELETE:// Table Name NULL |
|
377 case SQLITE_INSERT:// Table Name NULL |
|
378 case SQLITE_UPDATE:// Table Name Column Name |
|
379 if(!inspector.Check(schemaPolicy)) |
|
380 { |
|
381 res = SQLITE_DENY; |
|
382 if(!::IsSqliteTableName(tblName)) |
|
383 { |
|
384 if(inspector.Check(writePolicy)) |
|
385 { |
|
386 res = SQLITE_OK; |
|
387 } |
|
388 } |
|
389 } |
|
390 break; |
|
391 //"Database schema policy" || "Database read policy" || "Database write policy" for sqlite tables |
|
392 //"Database schema policy" || "Database read policy" for user tables |
|
393 case SQLITE_READ:// Table Name Column Name |
|
394 if(!(inspector.Check(schemaPolicy) || inspector.Check(readPolicy))) |
|
395 { |
|
396 res = SQLITE_DENY; |
|
397 if(::IsSqliteTableName(tblName)) |
|
398 { |
|
399 if(inspector.Check(writePolicy)) |
|
400 { |
|
401 res = SQLITE_OK; |
|
402 } |
|
403 } |
|
404 } |
|
405 break; |
|
406 case SQLITE_PRAGMA:// Pragma Name 1st arg or NULL |
|
407 res = PragmaCheck(aDbObjName1, (aDbObjName2 != NULL), ETrue); |
|
408 break; |
|
409 case SQLITE_ATTACH:// Filename NULL |
|
410 case SQLITE_DETACH:// Database Name NULL |
|
411 //If the operation is SQLITE_ATTACH or SQLITE_DETACH, return SQLITE_DENY. |
|
412 //"ATTACH DATABASE"/"DETACH DATABASE" operations are performed by separate "attach/detach db" methods. |
|
413 res = SQLITE_DENY; |
|
414 break; |
|
415 //No policy check |
|
416 case SQLITE_REINDEX:// Index Name NULL |
|
417 case SQLITE_ANALYZE:// Table Name NULL |
|
418 break; |
|
419 case SQLITE_CREATE_VTABLE: |
|
420 case SQLITE_DROP_VTABLE: |
|
421 __SQLASSERT(EFalse, ESqlPanicInternalError); |
|
422 res = SQLITE_DENY; |
|
423 //No policy check |
|
424 case SQLITE_FUNCTION: |
|
425 break; |
|
426 default: |
|
427 __SQLASSERT(EFalse, ESqlPanicInternalError); |
|
428 break; |
|
429 } |
|
430 return res; |
|
431 } |
|
432 |
|
433 /** |
|
434 This callback function is invoked by the SQLITE engine at SQL statement compile time |
|
435 for each attempt to access a column of a table in the database. |
|
436 |
|
437 The callback returns SQLITE_OK if access is allowed, |
|
438 SQLITE_DENY if the entire SQL statement should be aborted with an error and |
|
439 SQLITE_IGNORE if the column should be treated as a NULL value. |
|
440 |
|
441 @param aDb "This" pointer (to the rellated CSqlSrvDatabase object). |
|
442 @param aDbOpType Database operation type, which needs to be authorized. It could be one of these: |
|
443 |
|
444 @code |
|
445 ================================================================= |
|
446 aDbOpType aDbObjName1 aDbObjName2 |
|
447 ================================================================= |
|
448 SQLITE_CREATE_INDEX Index Name Table Name |
|
449 SQLITE_CREATE_TABLE Table Name NULL |
|
450 SQLITE_CREATE_TEMP_INDEX Index Name Table Name |
|
451 SQLITE_CREATE_TEMP_TABLE Table Name NULL |
|
452 SQLITE_CREATE_TEMP_TRIGGER Trigger Name Table Name |
|
453 SQLITE_CREATE_TEMP_VIEW View Name NULL |
|
454 SQLITE_CREATE_TRIGGER Trigger Name Table Name |
|
455 SQLITE_CREATE_VIEW View Name NULL |
|
456 SQLITE_DELETE Table Name NULL |
|
457 SQLITE_DROP_INDEX Index Name Table Name |
|
458 SQLITE_DROP_TABLE Table Name NULL |
|
459 SQLITE_DROP_TEMP_INDEX Index Name Table Name |
|
460 SQLITE_DROP_TEMP_TABLE Table Name NULL |
|
461 SQLITE_DROP_TEMP_TRIGGER Trigger Name Table Name |
|
462 SQLITE_DROP_TEMP_VIEW View Name NULL |
|
463 SQLITE_DROP_TRIGGER Trigger Name Table Name |
|
464 SQLITE_DROP_VIEW View Name NULL |
|
465 SQLITE_INSERT Table Name NULL |
|
466 SQLITE_PRAGMA Pragma Name 1st arg or NULL |
|
467 SQLITE_READ Table Name Column Name |
|
468 SQLITE_SELECT NULL NULL |
|
469 SQLITE_TRANSACTION NULL NULL |
|
470 SQLITE_UPDATE Table Name Column Name |
|
471 SQLITE_ATTACH Filename NULL |
|
472 SQLITE_DETACH Database Name NULL |
|
473 SQLITE_ALTER_TABLE Database Name Table Name |
|
474 SQLITE_REINDEX Index Name NULL |
|
475 SQLITE_ANALYZE Table Name NULL |
|
476 SQLITE_CREATE_VTABLE Table Name Module Name |
|
477 SQLITE_DROP_VTABLE Table Name Module Name |
|
478 SQLITE_FUNCTION Function Name NULL |
|
479 ================================================================= |
|
480 @endcode |
|
481 |
|
482 @param aDbObjName1 Database, Table, View, Trigger, Index, Pragma or File name. It depends on the |
|
483 values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
484 @param aDbObjName2 Table or Column name. It depends on the values of aDbOpType argument. UTF8 encoded, zero-terminated. |
|
485 @param aDbName Database name - "main", "temp", etc. UTF8 encoded, zero-terminated. |
|
486 @param aTrgOrViewName The name of the inner-most trigger or view that is responsible for the access |
|
487 attempt or NULL if this access attempt is directly from input SQL code. UTF8 encoded, zero-terminated. |
|
488 |
|
489 @return SQLITE_OK Access is allowed |
|
490 @return SQLITE_DENY The entire SQL statement should be aborted |
|
491 @return SQLITE_IGNORE The column should be treated as it has NULL value |
|
492 |
|
493 @panic SqlDb 4 In _DEBUG mode. The authorizer was called with NULL aDb argument. |
|
494 |
|
495 @internalComponent |
|
496 */ |
|
497 TInt CSqlSrvDatabase::AuthorizeCallback(void* aDb, TInt aDbOpType, |
|
498 const char* aDbObjName1, const char* aDbObjName2, |
|
499 const char* aDbName, const char* aTrgOrViewName) |
|
500 { |
|
501 UNUSED_ARG(aTrgOrViewName); |
|
502 __SQLASSERT(aDb != NULL, ESqlPanicBadArgument); |
|
503 |
|
504 #ifdef _NOTIFY |
|
505 enum TDbOpType {EOpCreateIndex = 1, EOpCreateTable, EOpCreateTempIndex, EOpCreateTempTable, |
|
506 EOpCreateTempTrigger, EOpCreateTempView, EOpCreateTrigger, EOpCreateView, EOpDelete, EOpDropIndex, |
|
507 EOpDropTable, EOpDropTempIndex, EOpDropTempTable, EOpDropTempTrigger, EOpDropTempView, EOpDropTrigger, |
|
508 EOpDropView, EOpInsert, EOpPragma, EOpRead, EOpSelect, EOpTransaction, EOpUpdate, EOpAttach, EOpDettach, |
|
509 EOpAlterTable, EOpReindex, EOpAnalyze, EOpCreateVTable, EOpDropVTable, EOpFunctionCall}; |
|
510 TDbOpType dbOpType = static_cast <TDbOpType> (aDbOpType);//can be seen now in the debugger |
|
511 ::PrintAuthorizerArguments(dbOpType, aDbObjName1, aDbObjName2, aDbName, aTrgOrViewName); |
|
512 #endif//_NOTIFY |
|
513 |
|
514 CSqlSrvDatabase& db = *static_cast <CSqlSrvDatabase*> (aDb); |
|
515 |
|
516 //1. If the authorizer is currently disabled - return SQLITE_OK. |
|
517 // (This happens when a database is attached/detached) |
|
518 if(db.iAuthorizerDisabled) |
|
519 { |
|
520 return SQLITE_OK; |
|
521 } |
|
522 |
|
523 TPtrC8 dbName(KNullDesC8); |
|
524 const char* dbNamePtr = DbOp2DbName(aDbOpType, aDbObjName1, aDbName);//dbNamePtr is zero terminated |
|
525 if(dbNamePtr) |
|
526 { |
|
527 dbName.Set(reinterpret_cast <const TUint8*> (dbNamePtr)); |
|
528 } |
|
529 aDbName = NULL;//No more use of aDbName argument inside the function. |
|
530 |
|
531 //2. If the database name is KTempDb, then allow the access. It is a local database |
|
532 // (for the client), deleted when closed. |
|
533 if(dbName.Compare(KTempDb8) == 0) //dbName is guaranteed to be in lower case if it is "temp", |
|
534 { //so it is possible to use binary string comparison |
|
535 return SQLITE_OK; |
|
536 } |
|
537 |
|
538 //3. Find the security policies. For DefaultAccess initialized with NULL. |
|
539 const CSqlSecurityPolicy* securityPolicy = NULL; |
|
540 if(dbName.Compare(KMainDb8) == 0||dbName.Length() == 0) //dbName is guaranteed to be in lower case if it is "main", |
|
541 { //so it is possible to use binary string comparison |
|
542 //4. This is the main database. |
|
543 securityPolicy = db.iSecurityPolicy; |
|
544 } |
|
545 else |
|
546 { |
|
547 //5. This is an attached database. Find the attached database security policies. |
|
548 //dbNamePtr is used here because it is zero terminated |
|
549 TSqlAttachDbPair* attachDbPair = db.iAttachDbMap.Entry(reinterpret_cast <const TUint8*> (dbNamePtr)); |
|
550 if(attachDbPair) |
|
551 {//secure database, find the security policies |
|
552 const TUint8* securityMapKey = attachDbPair->iData; |
|
553 RSqlSecurityMap& map = ::SqlServer().SecurityMap(); |
|
554 TSqlSecurityPair* pair = map.Entry(securityMapKey); |
|
555 if(pair) |
|
556 { |
|
557 securityPolicy = pair->iData; |
|
558 } |
|
559 } |
|
560 } |
|
561 |
|
562 //Here we have: |
|
563 // - valid database name (not NULL); |
|
564 |
|
565 //6. Default or Security Policy Checks |
|
566 return !securityPolicy ? NonSecureChecks(aDbOpType,aDbObjName1,aDbObjName2): SecureChecks(securityPolicy,aDbOpType,aDbObjName1,aDbObjName2); |
|
567 } |