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 #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