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