Home | History | Annotate | Download | only in storage
      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