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