• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DatabaseAuthorizer()37 DatabaseAuthorizer::DatabaseAuthorizer()
38     : m_securityEnabled(false)
39 {
40     reset();
41     addWhitelistedFunctions();
42 }
43 
reset()44 void DatabaseAuthorizer::reset()
45 {
46     m_lastActionWasInsert = false;
47     m_lastActionChangedDatabase = false;
48     m_readOnly = false;
49 }
50 
addWhitelistedFunctions()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 
createTable(const String & tableName)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 
createTempTable(const String & tableName)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 
dropTable(const String & tableName)134 int DatabaseAuthorizer::dropTable(const String& tableName)
135 {
136     if (m_readOnly && m_securityEnabled)
137         return SQLAuthDeny;
138 
139     return denyBasedOnTableName(tableName);
140 }
141 
dropTempTable(const String & tableName)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 
allowAlterTable(const String &,const String & tableName)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 
createIndex(const String &,const String & tableName)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 
createTempIndex(const String &,const String & tableName)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 
dropIndex(const String &,const String & tableName)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 
dropTempIndex(const String &,const String & tableName)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 
createTrigger(const String &,const String & tableName)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 
createTempTrigger(const String &,const String & tableName)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 
dropTrigger(const String &,const String & tableName)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 
dropTempTrigger(const String &,const String & tableName)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 
createView(const String &)240 int DatabaseAuthorizer::createView(const String&)
241 {
242     return (m_readOnly && m_securityEnabled ? SQLAuthDeny : SQLAuthAllow);
243 }
244 
createTempView(const String &)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 
dropView(const String &)253 int DatabaseAuthorizer::dropView(const String&)
254 {
255     return (m_readOnly && m_securityEnabled ? SQLAuthDeny : SQLAuthAllow);
256 }
257 
dropTempView(const String &)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 
createVTable(const String &,const String &)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 
dropVTable(const String &,const String &)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 
allowDelete(const String & tableName)283 int DatabaseAuthorizer::allowDelete(const String& tableName)
284 {
285     if (m_readOnly && m_securityEnabled)
286         return SQLAuthDeny;
287 
288     return denyBasedOnTableName(tableName);
289 }
290 
allowInsert(const String & tableName)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 
allowUpdate(const String & tableName,const String &)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 
allowTransaction()310 int DatabaseAuthorizer::allowTransaction()
311 {
312     return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
313 }
314 
allowRead(const String & tableName,const String &)315 int DatabaseAuthorizer::allowRead(const String& tableName, const String&)
316 {
317     return denyBasedOnTableName(tableName);
318 }
319 
allowReindex(const String &)320 int DatabaseAuthorizer::allowReindex(const String&)
321 {
322     return (m_readOnly && m_securityEnabled ? SQLAuthDeny : SQLAuthAllow);
323 }
324 
allowAnalyze(const String & tableName)325 int DatabaseAuthorizer::allowAnalyze(const String& tableName)
326 {
327     return denyBasedOnTableName(tableName);
328 }
329 
allowPragma(const String &,const String &)330 int DatabaseAuthorizer::allowPragma(const String&, const String&)
331 {
332     return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
333 }
334 
allowAttach(const String &)335 int DatabaseAuthorizer::allowAttach(const String&)
336 {
337     return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
338 }
339 
allowDetach(const String &)340 int DatabaseAuthorizer::allowDetach(const String&)
341 {
342     return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
343 }
344 
allowFunction(const String & functionName)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 
disable()353 void DatabaseAuthorizer::disable()
354 {
355     m_securityEnabled = false;
356 }
357 
enable()358 void DatabaseAuthorizer::enable()
359 {
360     m_securityEnabled = true;
361 }
362 
setReadOnly()363 void DatabaseAuthorizer::setReadOnly()
364 {
365     m_readOnly = true;
366 }
367 
denyBasedOnTableName(const String & tableName)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