1 /* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "DatabaseAuthorizer.h" 31 32 #if ENABLE(DATABASE) 33 34 #include "PlatformString.h" 35 #include <wtf/PassRefPtr.h> 36 37 namespace WebCore { 38 39 PassRefPtr<DatabaseAuthorizer> DatabaseAuthorizer::create(const String& databaseInfoTableName) 40 { 41 return adoptRef(new DatabaseAuthorizer(databaseInfoTableName)); 42 } 43 44 DatabaseAuthorizer::DatabaseAuthorizer(const String& databaseInfoTableName) 45 : m_securityEnabled(false) 46 , m_databaseInfoTableName(databaseInfoTableName) 47 { 48 reset(); 49 addWhitelistedFunctions(); 50 } 51 52 void DatabaseAuthorizer::reset() 53 { 54 m_lastActionWasInsert = false; 55 m_lastActionChangedDatabase = false; 56 m_permissions = ReadWriteMask; 57 } 58 59 void DatabaseAuthorizer::resetDeletes() 60 { 61 m_hadDeletes = false; 62 } 63 64 void DatabaseAuthorizer::addWhitelistedFunctions() 65 { 66 // SQLite functions used to help implement some operations 67 // ALTER TABLE helpers 68 m_whitelistedFunctions.add("sqlite_rename_table"); 69 m_whitelistedFunctions.add("sqlite_rename_trigger"); 70 // GLOB helpers 71 m_whitelistedFunctions.add("glob"); 72 73 // SQLite core functions 74 m_whitelistedFunctions.add("abs"); 75 m_whitelistedFunctions.add("changes"); 76 m_whitelistedFunctions.add("coalesce"); 77 m_whitelistedFunctions.add("glob"); 78 m_whitelistedFunctions.add("ifnull"); 79 m_whitelistedFunctions.add("hex"); 80 m_whitelistedFunctions.add("last_insert_rowid"); 81 m_whitelistedFunctions.add("length"); 82 m_whitelistedFunctions.add("like"); 83 m_whitelistedFunctions.add("lower"); 84 m_whitelistedFunctions.add("ltrim"); 85 m_whitelistedFunctions.add("max"); 86 m_whitelistedFunctions.add("min"); 87 m_whitelistedFunctions.add("nullif"); 88 m_whitelistedFunctions.add("quote"); 89 m_whitelistedFunctions.add("replace"); 90 m_whitelistedFunctions.add("round"); 91 m_whitelistedFunctions.add("rtrim"); 92 m_whitelistedFunctions.add("soundex"); 93 m_whitelistedFunctions.add("sqlite_source_id"); 94 m_whitelistedFunctions.add("sqlite_version"); 95 m_whitelistedFunctions.add("substr"); 96 m_whitelistedFunctions.add("total_changes"); 97 m_whitelistedFunctions.add("trim"); 98 m_whitelistedFunctions.add("typeof"); 99 m_whitelistedFunctions.add("upper"); 100 m_whitelistedFunctions.add("zeroblob"); 101 102 // SQLite date and time functions 103 m_whitelistedFunctions.add("date"); 104 m_whitelistedFunctions.add("time"); 105 m_whitelistedFunctions.add("datetime"); 106 m_whitelistedFunctions.add("julianday"); 107 m_whitelistedFunctions.add("strftime"); 108 109 // SQLite aggregate functions 110 // max() and min() are already in the list 111 m_whitelistedFunctions.add("avg"); 112 m_whitelistedFunctions.add("count"); 113 m_whitelistedFunctions.add("group_concat"); 114 m_whitelistedFunctions.add("sum"); 115 m_whitelistedFunctions.add("total"); 116 117 // SQLite FTS functions 118 m_whitelistedFunctions.add("match"); 119 m_whitelistedFunctions.add("snippet"); 120 m_whitelistedFunctions.add("offsets"); 121 m_whitelistedFunctions.add("optimize"); 122 123 // SQLite ICU functions 124 // like(), lower() and upper() are already in the list 125 m_whitelistedFunctions.add("regexp"); 126 } 127 128 int DatabaseAuthorizer::createTable(const String& tableName) 129 { 130 if (!allowWrite()) 131 return SQLAuthDeny; 132 133 m_lastActionChangedDatabase = true; 134 return denyBasedOnTableName(tableName); 135 } 136 137 int DatabaseAuthorizer::createTempTable(const String& tableName) 138 { 139 // SQLITE_CREATE_TEMP_TABLE results in a UPDATE operation, which is not 140 // allowed in read-only transactions or private browsing, so we might as 141 // well disallow SQLITE_CREATE_TEMP_TABLE in these cases 142 if (!allowWrite()) 143 return SQLAuthDeny; 144 145 return denyBasedOnTableName(tableName); 146 } 147 148 int DatabaseAuthorizer::dropTable(const String& tableName) 149 { 150 if (!allowWrite()) 151 return SQLAuthDeny; 152 153 return updateDeletesBasedOnTableName(tableName); 154 } 155 156 int DatabaseAuthorizer::dropTempTable(const String& tableName) 157 { 158 // SQLITE_DROP_TEMP_TABLE results in a DELETE operation, which is not 159 // allowed in read-only transactions or private browsing, so we might as 160 // well disallow SQLITE_DROP_TEMP_TABLE in these cases 161 if (!allowWrite()) 162 return SQLAuthDeny; 163 164 return updateDeletesBasedOnTableName(tableName); 165 } 166 167 int DatabaseAuthorizer::allowAlterTable(const String&, const String& tableName) 168 { 169 if (!allowWrite()) 170 return SQLAuthDeny; 171 172 m_lastActionChangedDatabase = true; 173 return denyBasedOnTableName(tableName); 174 } 175 176 int DatabaseAuthorizer::createIndex(const String&, const String& tableName) 177 { 178 if (!allowWrite()) 179 return SQLAuthDeny; 180 181 m_lastActionChangedDatabase = true; 182 return denyBasedOnTableName(tableName); 183 } 184 185 int DatabaseAuthorizer::createTempIndex(const String&, const String& tableName) 186 { 187 // SQLITE_CREATE_TEMP_INDEX should result in a UPDATE or INSERT operation, 188 // which is not allowed in read-only transactions or private browsing, 189 // so we might as well disallow SQLITE_CREATE_TEMP_INDEX in these cases 190 if (!allowWrite()) 191 return SQLAuthDeny; 192 193 return denyBasedOnTableName(tableName); 194 } 195 196 int DatabaseAuthorizer::dropIndex(const String&, const String& tableName) 197 { 198 if (!allowWrite()) 199 return SQLAuthDeny; 200 201 return updateDeletesBasedOnTableName(tableName); 202 } 203 204 int DatabaseAuthorizer::dropTempIndex(const String&, const String& tableName) 205 { 206 // SQLITE_DROP_TEMP_INDEX should result in a DELETE operation, which is 207 // not allowed in read-only transactions or private browsing, so we might 208 // as well disallow SQLITE_DROP_TEMP_INDEX in these cases 209 if (!allowWrite()) 210 return SQLAuthDeny; 211 212 return updateDeletesBasedOnTableName(tableName); 213 } 214 215 int DatabaseAuthorizer::createTrigger(const String&, const String& tableName) 216 { 217 if (!allowWrite()) 218 return SQLAuthDeny; 219 220 m_lastActionChangedDatabase = true; 221 return denyBasedOnTableName(tableName); 222 } 223 224 int DatabaseAuthorizer::createTempTrigger(const String&, const String& tableName) 225 { 226 // SQLITE_CREATE_TEMP_TRIGGER results in a INSERT operation, which is not 227 // allowed in read-only transactions or private browsing, so we might as 228 // well disallow SQLITE_CREATE_TEMP_TRIGGER in these cases 229 if (!allowWrite()) 230 return SQLAuthDeny; 231 232 return denyBasedOnTableName(tableName); 233 } 234 235 int DatabaseAuthorizer::dropTrigger(const String&, const String& tableName) 236 { 237 if (!allowWrite()) 238 return SQLAuthDeny; 239 240 return updateDeletesBasedOnTableName(tableName); 241 } 242 243 int DatabaseAuthorizer::dropTempTrigger(const String&, const String& tableName) 244 { 245 // SQLITE_DROP_TEMP_TRIGGER results in a DELETE operation, which is not 246 // allowed in read-only transactions or private browsing, so we might as 247 // well disallow SQLITE_DROP_TEMP_TRIGGER in these cases 248 if (!allowWrite()) 249 return SQLAuthDeny; 250 251 return updateDeletesBasedOnTableName(tableName); 252 } 253 254 int DatabaseAuthorizer::createView(const String&) 255 { 256 return (!allowWrite() ? SQLAuthDeny : SQLAuthAllow); 257 } 258 259 int DatabaseAuthorizer::createTempView(const String&) 260 { 261 // SQLITE_CREATE_TEMP_VIEW results in a UPDATE operation, which is not 262 // allowed in read-only transactions or private browsing, so we might as 263 // well disallow SQLITE_CREATE_TEMP_VIEW in these cases 264 return (!allowWrite() ? SQLAuthDeny : SQLAuthAllow); 265 } 266 267 int DatabaseAuthorizer::dropView(const String&) 268 { 269 if (!allowWrite()) 270 return SQLAuthDeny; 271 272 m_hadDeletes = true; 273 return SQLAuthAllow; 274 } 275 276 int DatabaseAuthorizer::dropTempView(const String&) 277 { 278 // SQLITE_DROP_TEMP_VIEW results in a DELETE operation, which is not 279 // allowed in read-only transactions or private browsing, so we might as 280 // well disallow SQLITE_DROP_TEMP_VIEW in these cases 281 if (!allowWrite()) 282 return SQLAuthDeny; 283 284 m_hadDeletes = true; 285 return SQLAuthAllow; 286 } 287 288 int DatabaseAuthorizer::createVTable(const String& tableName, const String& moduleName) 289 { 290 if (!allowWrite()) 291 return SQLAuthDeny; 292 293 // Allow only the FTS3 extension 294 if (!equalIgnoringCase(moduleName, "fts3")) 295 return SQLAuthDeny; 296 297 m_lastActionChangedDatabase = true; 298 return denyBasedOnTableName(tableName); 299 } 300 301 int DatabaseAuthorizer::dropVTable(const String& tableName, const String& moduleName) 302 { 303 if (!allowWrite()) 304 return SQLAuthDeny; 305 306 // Allow only the FTS3 extension 307 if (!equalIgnoringCase(moduleName, "fts3")) 308 return SQLAuthDeny; 309 310 return updateDeletesBasedOnTableName(tableName); 311 } 312 313 int DatabaseAuthorizer::allowDelete(const String& tableName) 314 { 315 if (!allowWrite()) 316 return SQLAuthDeny; 317 318 return updateDeletesBasedOnTableName(tableName); 319 } 320 321 int DatabaseAuthorizer::allowInsert(const String& tableName) 322 { 323 if (!allowWrite()) 324 return SQLAuthDeny; 325 326 m_lastActionChangedDatabase = true; 327 m_lastActionWasInsert = true; 328 return denyBasedOnTableName(tableName); 329 } 330 331 int DatabaseAuthorizer::allowUpdate(const String& tableName, const String&) 332 { 333 if (!allowWrite()) 334 return SQLAuthDeny; 335 336 m_lastActionChangedDatabase = true; 337 return denyBasedOnTableName(tableName); 338 } 339 340 int DatabaseAuthorizer::allowTransaction() 341 { 342 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 343 } 344 345 int DatabaseAuthorizer::allowRead(const String& tableName, const String&) 346 { 347 if (m_permissions & NoAccessMask && m_securityEnabled) 348 return SQLAuthDeny; 349 350 return denyBasedOnTableName(tableName); 351 } 352 353 int DatabaseAuthorizer::allowReindex(const String&) 354 { 355 return (!allowWrite() ? SQLAuthDeny : SQLAuthAllow); 356 } 357 358 int DatabaseAuthorizer::allowAnalyze(const String& tableName) 359 { 360 return denyBasedOnTableName(tableName); 361 } 362 363 int DatabaseAuthorizer::allowPragma(const String&, const String&) 364 { 365 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 366 } 367 368 int DatabaseAuthorizer::allowAttach(const String&) 369 { 370 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 371 } 372 373 int DatabaseAuthorizer::allowDetach(const String&) 374 { 375 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 376 } 377 378 int DatabaseAuthorizer::allowFunction(const String& functionName) 379 { 380 if (m_securityEnabled && !m_whitelistedFunctions.contains(functionName)) 381 return SQLAuthDeny; 382 383 return SQLAuthAllow; 384 } 385 386 void DatabaseAuthorizer::disable() 387 { 388 m_securityEnabled = false; 389 } 390 391 void DatabaseAuthorizer::enable() 392 { 393 m_securityEnabled = true; 394 } 395 396 bool DatabaseAuthorizer::allowWrite() 397 { 398 return !(m_securityEnabled && (m_permissions & ReadOnlyMask || m_permissions & NoAccessMask)); 399 } 400 401 void DatabaseAuthorizer::setReadOnly() 402 { 403 m_permissions |= ReadOnlyMask; 404 } 405 406 void DatabaseAuthorizer::setPermissions(int permissions) 407 { 408 m_permissions = permissions; 409 } 410 411 int DatabaseAuthorizer::denyBasedOnTableName(const String& tableName) const 412 { 413 if (!m_securityEnabled) 414 return SQLAuthAllow; 415 416 // Sadly, normal creates and drops end up affecting sqlite_master in an authorizer callback, so 417 // it will be tough to enforce all of the following policies 418 //if (equalIgnoringCase(tableName, "sqlite_master") || equalIgnoringCase(tableName, "sqlite_temp_master") || 419 // equalIgnoringCase(tableName, "sqlite_sequence") || equalIgnoringCase(tableName, Database::databaseInfoTableName())) 420 // return SQLAuthDeny; 421 422 if (equalIgnoringCase(tableName, m_databaseInfoTableName)) 423 return SQLAuthDeny; 424 425 return SQLAuthAllow; 426 } 427 428 int DatabaseAuthorizer::updateDeletesBasedOnTableName(const String& tableName) 429 { 430 int allow = denyBasedOnTableName(tableName); 431 if (allow) 432 m_hadDeletes = true; 433 return allow; 434 } 435 436 } // namespace WebCore 437 438 #endif 439