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 "modules/webdatabase/DatabaseAuthorizer.h" 31 32 #include "wtf/PassRefPtr.h" 33 34 namespace WebCore { 35 36 PassRefPtr<DatabaseAuthorizer> DatabaseAuthorizer::create(const String& databaseInfoTableName) 37 { 38 return adoptRef(new DatabaseAuthorizer(databaseInfoTableName)); 39 } 40 41 DatabaseAuthorizer::DatabaseAuthorizer(const String& databaseInfoTableName) 42 : m_securityEnabled(false) 43 , m_databaseInfoTableName(databaseInfoTableName) 44 { 45 reset(); 46 addWhitelistedFunctions(); 47 } 48 49 void DatabaseAuthorizer::reset() 50 { 51 m_lastActionWasInsert = false; 52 m_lastActionChangedDatabase = false; 53 m_permissions = ReadWriteMask; 54 } 55 56 void DatabaseAuthorizer::resetDeletes() 57 { 58 m_hadDeletes = false; 59 } 60 61 void DatabaseAuthorizer::addWhitelistedFunctions() 62 { 63 // SQLite functions used to help implement some operations 64 // ALTER TABLE helpers 65 m_whitelistedFunctions.add("sqlite_rename_table"); 66 m_whitelistedFunctions.add("sqlite_rename_trigger"); 67 // GLOB helpers 68 m_whitelistedFunctions.add("glob"); 69 70 // SQLite core functions 71 m_whitelistedFunctions.add("abs"); 72 m_whitelistedFunctions.add("changes"); 73 m_whitelistedFunctions.add("coalesce"); 74 m_whitelistedFunctions.add("glob"); 75 m_whitelistedFunctions.add("ifnull"); 76 m_whitelistedFunctions.add("hex"); 77 m_whitelistedFunctions.add("last_insert_rowid"); 78 m_whitelistedFunctions.add("length"); 79 m_whitelistedFunctions.add("like"); 80 m_whitelistedFunctions.add("lower"); 81 m_whitelistedFunctions.add("ltrim"); 82 m_whitelistedFunctions.add("max"); 83 m_whitelistedFunctions.add("min"); 84 m_whitelistedFunctions.add("nullif"); 85 m_whitelistedFunctions.add("quote"); 86 m_whitelistedFunctions.add("replace"); 87 m_whitelistedFunctions.add("round"); 88 m_whitelistedFunctions.add("rtrim"); 89 m_whitelistedFunctions.add("soundex"); 90 m_whitelistedFunctions.add("sqlite_source_id"); 91 m_whitelistedFunctions.add("sqlite_version"); 92 m_whitelistedFunctions.add("substr"); 93 m_whitelistedFunctions.add("total_changes"); 94 m_whitelistedFunctions.add("trim"); 95 m_whitelistedFunctions.add("typeof"); 96 m_whitelistedFunctions.add("upper"); 97 m_whitelistedFunctions.add("zeroblob"); 98 99 // SQLite date and time functions 100 m_whitelistedFunctions.add("date"); 101 m_whitelistedFunctions.add("time"); 102 m_whitelistedFunctions.add("datetime"); 103 m_whitelistedFunctions.add("julianday"); 104 m_whitelistedFunctions.add("strftime"); 105 106 // SQLite aggregate functions 107 // max() and min() are already in the list 108 m_whitelistedFunctions.add("avg"); 109 m_whitelistedFunctions.add("count"); 110 m_whitelistedFunctions.add("group_concat"); 111 m_whitelistedFunctions.add("sum"); 112 m_whitelistedFunctions.add("total"); 113 114 // SQLite FTS functions 115 m_whitelistedFunctions.add("match"); 116 m_whitelistedFunctions.add("snippet"); 117 m_whitelistedFunctions.add("offsets"); 118 m_whitelistedFunctions.add("optimize"); 119 120 // SQLite ICU functions 121 // like(), lower() and upper() are already in the list 122 m_whitelistedFunctions.add("regexp"); 123 } 124 125 int DatabaseAuthorizer::createTable(const String& tableName) 126 { 127 if (!allowWrite()) 128 return SQLAuthDeny; 129 130 m_lastActionChangedDatabase = true; 131 return denyBasedOnTableName(tableName); 132 } 133 134 int DatabaseAuthorizer::createTempTable(const String& tableName) 135 { 136 // SQLITE_CREATE_TEMP_TABLE results in a UPDATE operation, which is not 137 // allowed in read-only transactions or private browsing, so we might as 138 // well disallow SQLITE_CREATE_TEMP_TABLE in these cases 139 if (!allowWrite()) 140 return SQLAuthDeny; 141 142 return denyBasedOnTableName(tableName); 143 } 144 145 int DatabaseAuthorizer::dropTable(const String& tableName) 146 { 147 if (!allowWrite()) 148 return SQLAuthDeny; 149 150 return updateDeletesBasedOnTableName(tableName); 151 } 152 153 int DatabaseAuthorizer::dropTempTable(const String& tableName) 154 { 155 // SQLITE_DROP_TEMP_TABLE results in a DELETE operation, which is not 156 // allowed in read-only transactions or private browsing, so we might as 157 // well disallow SQLITE_DROP_TEMP_TABLE in these cases 158 if (!allowWrite()) 159 return SQLAuthDeny; 160 161 return updateDeletesBasedOnTableName(tableName); 162 } 163 164 int DatabaseAuthorizer::allowAlterTable(const String&, const String& tableName) 165 { 166 if (!allowWrite()) 167 return SQLAuthDeny; 168 169 m_lastActionChangedDatabase = true; 170 return denyBasedOnTableName(tableName); 171 } 172 173 int DatabaseAuthorizer::createIndex(const String&, const String& tableName) 174 { 175 if (!allowWrite()) 176 return SQLAuthDeny; 177 178 m_lastActionChangedDatabase = true; 179 return denyBasedOnTableName(tableName); 180 } 181 182 int DatabaseAuthorizer::createTempIndex(const String&, const String& tableName) 183 { 184 // SQLITE_CREATE_TEMP_INDEX should result in a UPDATE or INSERT operation, 185 // which is not allowed in read-only transactions or private browsing, 186 // so we might as well disallow SQLITE_CREATE_TEMP_INDEX in these cases 187 if (!allowWrite()) 188 return SQLAuthDeny; 189 190 return denyBasedOnTableName(tableName); 191 } 192 193 int DatabaseAuthorizer::dropIndex(const String&, const String& tableName) 194 { 195 if (!allowWrite()) 196 return SQLAuthDeny; 197 198 return updateDeletesBasedOnTableName(tableName); 199 } 200 201 int DatabaseAuthorizer::dropTempIndex(const String&, const String& tableName) 202 { 203 // SQLITE_DROP_TEMP_INDEX should result in a DELETE operation, which is 204 // not allowed in read-only transactions or private browsing, so we might 205 // as well disallow SQLITE_DROP_TEMP_INDEX in these cases 206 if (!allowWrite()) 207 return SQLAuthDeny; 208 209 return updateDeletesBasedOnTableName(tableName); 210 } 211 212 int DatabaseAuthorizer::createTrigger(const String&, const String& tableName) 213 { 214 if (!allowWrite()) 215 return SQLAuthDeny; 216 217 m_lastActionChangedDatabase = true; 218 return denyBasedOnTableName(tableName); 219 } 220 221 int DatabaseAuthorizer::createTempTrigger(const String&, const String& tableName) 222 { 223 // SQLITE_CREATE_TEMP_TRIGGER results in a INSERT operation, which is not 224 // allowed in read-only transactions or private browsing, so we might as 225 // well disallow SQLITE_CREATE_TEMP_TRIGGER in these cases 226 if (!allowWrite()) 227 return SQLAuthDeny; 228 229 return denyBasedOnTableName(tableName); 230 } 231 232 int DatabaseAuthorizer::dropTrigger(const String&, const String& tableName) 233 { 234 if (!allowWrite()) 235 return SQLAuthDeny; 236 237 return updateDeletesBasedOnTableName(tableName); 238 } 239 240 int DatabaseAuthorizer::dropTempTrigger(const String&, const String& tableName) 241 { 242 // SQLITE_DROP_TEMP_TRIGGER results in a DELETE operation, which is not 243 // allowed in read-only transactions or private browsing, so we might as 244 // well disallow SQLITE_DROP_TEMP_TRIGGER in these cases 245 if (!allowWrite()) 246 return SQLAuthDeny; 247 248 return updateDeletesBasedOnTableName(tableName); 249 } 250 251 int DatabaseAuthorizer::createView(const String&) 252 { 253 return (!allowWrite() ? SQLAuthDeny : SQLAuthAllow); 254 } 255 256 int DatabaseAuthorizer::createTempView(const String&) 257 { 258 // SQLITE_CREATE_TEMP_VIEW results in a UPDATE operation, which is not 259 // allowed in read-only transactions or private browsing, so we might as 260 // well disallow SQLITE_CREATE_TEMP_VIEW in these cases 261 return (!allowWrite() ? SQLAuthDeny : SQLAuthAllow); 262 } 263 264 int DatabaseAuthorizer::dropView(const String&) 265 { 266 if (!allowWrite()) 267 return SQLAuthDeny; 268 269 m_hadDeletes = true; 270 return SQLAuthAllow; 271 } 272 273 int DatabaseAuthorizer::dropTempView(const String&) 274 { 275 // SQLITE_DROP_TEMP_VIEW results in a DELETE operation, which is not 276 // allowed in read-only transactions or private browsing, so we might as 277 // well disallow SQLITE_DROP_TEMP_VIEW in these cases 278 if (!allowWrite()) 279 return SQLAuthDeny; 280 281 m_hadDeletes = true; 282 return SQLAuthAllow; 283 } 284 285 int DatabaseAuthorizer::createVTable(const String& tableName, const String& moduleName) 286 { 287 if (!allowWrite()) 288 return SQLAuthDeny; 289 290 // Allow only the FTS3 extension 291 if (!equalIgnoringCase(moduleName, "fts3")) 292 return SQLAuthDeny; 293 294 m_lastActionChangedDatabase = true; 295 return denyBasedOnTableName(tableName); 296 } 297 298 int DatabaseAuthorizer::dropVTable(const String& tableName, const String& moduleName) 299 { 300 if (!allowWrite()) 301 return SQLAuthDeny; 302 303 // Allow only the FTS3 extension 304 if (!equalIgnoringCase(moduleName, "fts3")) 305 return SQLAuthDeny; 306 307 return updateDeletesBasedOnTableName(tableName); 308 } 309 310 int DatabaseAuthorizer::allowDelete(const String& tableName) 311 { 312 if (!allowWrite()) 313 return SQLAuthDeny; 314 315 return updateDeletesBasedOnTableName(tableName); 316 } 317 318 int DatabaseAuthorizer::allowInsert(const String& tableName) 319 { 320 if (!allowWrite()) 321 return SQLAuthDeny; 322 323 m_lastActionChangedDatabase = true; 324 m_lastActionWasInsert = true; 325 return denyBasedOnTableName(tableName); 326 } 327 328 int DatabaseAuthorizer::allowUpdate(const String& tableName, const String&) 329 { 330 if (!allowWrite()) 331 return SQLAuthDeny; 332 333 m_lastActionChangedDatabase = true; 334 return denyBasedOnTableName(tableName); 335 } 336 337 int DatabaseAuthorizer::allowTransaction() 338 { 339 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 340 } 341 342 int DatabaseAuthorizer::allowRead(const String& tableName, const String&) 343 { 344 if (m_permissions & NoAccessMask && m_securityEnabled) 345 return SQLAuthDeny; 346 347 return denyBasedOnTableName(tableName); 348 } 349 350 int DatabaseAuthorizer::allowReindex(const String&) 351 { 352 return (!allowWrite() ? SQLAuthDeny : SQLAuthAllow); 353 } 354 355 int DatabaseAuthorizer::allowAnalyze(const String& tableName) 356 { 357 return denyBasedOnTableName(tableName); 358 } 359 360 int DatabaseAuthorizer::allowPragma(const String&, const String&) 361 { 362 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 363 } 364 365 int DatabaseAuthorizer::allowAttach(const String&) 366 { 367 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 368 } 369 370 int DatabaseAuthorizer::allowDetach(const String&) 371 { 372 return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; 373 } 374 375 int DatabaseAuthorizer::allowFunction(const String& functionName) 376 { 377 if (m_securityEnabled && !m_whitelistedFunctions.contains(functionName)) 378 return SQLAuthDeny; 379 380 return SQLAuthAllow; 381 } 382 383 void DatabaseAuthorizer::disable() 384 { 385 m_securityEnabled = false; 386 } 387 388 void DatabaseAuthorizer::enable() 389 { 390 m_securityEnabled = true; 391 } 392 393 bool DatabaseAuthorizer::allowWrite() 394 { 395 return !(m_securityEnabled && (m_permissions & ReadOnlyMask || m_permissions & NoAccessMask)); 396 } 397 398 void DatabaseAuthorizer::setReadOnly() 399 { 400 m_permissions |= ReadOnlyMask; 401 } 402 403 void DatabaseAuthorizer::setPermissions(int permissions) 404 { 405 m_permissions = permissions; 406 } 407 408 int DatabaseAuthorizer::denyBasedOnTableName(const String& tableName) const 409 { 410 if (!m_securityEnabled) 411 return SQLAuthAllow; 412 413 // Sadly, normal creates and drops end up affecting sqlite_master in an authorizer callback, so 414 // it will be tough to enforce all of the following policies 415 //if (equalIgnoringCase(tableName, "sqlite_master") || equalIgnoringCase(tableName, "sqlite_temp_master") || 416 // equalIgnoringCase(tableName, "sqlite_sequence") || equalIgnoringCase(tableName, Database::databaseInfoTableName())) 417 // return SQLAuthDeny; 418 419 if (equalIgnoringCase(tableName, m_databaseInfoTableName)) 420 return SQLAuthDeny; 421 422 return SQLAuthAllow; 423 } 424 425 int DatabaseAuthorizer::updateDeletesBasedOnTableName(const String& tableName) 426 { 427 int allow = denyBasedOnTableName(tableName); 428 if (allow) 429 m_hadDeletes = true; 430 return allow; 431 } 432 433 } // namespace WebCore 434