xref: /sqlite-3.40.0/test/userauth01.test (revision 7883ecfc)
1d39c40ffSdrh# 2014-09-10
2d39c40ffSdrh#
3d39c40ffSdrh# The author disclaims copyright to this source code.  In place of
4d39c40ffSdrh# a legal notice, here is a blessing:
5d39c40ffSdrh#
6d39c40ffSdrh#    May you do good and not evil.
7d39c40ffSdrh#    May you find forgiveness for yourself and forgive others.
8d39c40ffSdrh#    May you share freely, never taking more than you give.
9d39c40ffSdrh#
10d39c40ffSdrh#***********************************************************************
11d39c40ffSdrh#
12d39c40ffSdrh# This file implements tests of the SQLITE_USER_AUTHENTICATION extension.
13d39c40ffSdrh#
14d39c40ffSdrh
15d39c40ffSdrhset testdir [file dirname $argv0]
16d39c40ffSdrhsource $testdir/tester.tcl
17d39c40ffSdrhset testprefix userauth01
18d39c40ffSdrh
19d39c40ffSdrhifcapable !userauth {
20d39c40ffSdrh  finish_test
21d39c40ffSdrh  return
22d39c40ffSdrh}
23d39c40ffSdrh
24d39c40ffSdrh# Create a no-authentication-required database
25d39c40ffSdrh#
26d39c40ffSdrhdo_execsql_test userauth01-1.0 {
27d39c40ffSdrh  CREATE TABLE t1(x);
28d39c40ffSdrh  INSERT INTO t1 VALUES(1),(2.5),('three'),(x'4444'),(NULL);
29d39c40ffSdrh  SELECT quote(x) FROM t1 ORDER BY x;
30d39c40ffSdrh  SELECT name FROM sqlite_master;
31d39c40ffSdrh} {NULL 1 2.5 'three' X'4444' t1}
32d39c40ffSdrh
33d39c40ffSdrh# Calling sqlite3_user_authenticate() on a no-authentication-required
34d39c40ffSdrh# database connection is a harmless no-op.
35d39c40ffSdrh#
36d39c40ffSdrhdo_test userauth01-1.1 {
37d39c40ffSdrh  sqlite3_user_authenticate db alice pw-4-alice
38d39c40ffSdrh  execsql {
39d39c40ffSdrh    SELECT quote(x) FROM t1 ORDER BY x;
40d39c40ffSdrh    SELECT name FROM sqlite_master;
41d39c40ffSdrh  }
42d39c40ffSdrh} {NULL 1 2.5 'three' X'4444' t1}
43d39c40ffSdrh
44d39c40ffSdrh# If sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
45d39c40ffSdrh# database and A is false, then the call fails with an SQLITE_AUTH error.
46d39c40ffSdrh#
47d39c40ffSdrhdo_test userauth01-1.2 {
48d39c40ffSdrh  sqlite3_user_add db bob pw-4-bob 0
49d39c40ffSdrh} {SQLITE_AUTH}
50d39c40ffSdrhdo_test userauth01-1.3 {
51d39c40ffSdrh  execsql {
52d39c40ffSdrh    SELECT quote(x) FROM t1 ORDER BY x;
53d39c40ffSdrh    SELECT name FROM sqlite_master;
54d39c40ffSdrh  }
55d39c40ffSdrh} {NULL 1 2.5 'three' X'4444' t1}
56d39c40ffSdrh
57d39c40ffSdrh# When called on a no-authentication-required
58d39c40ffSdrh# database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
59d39c40ffSdrh# converts the database into an authentication-required database and
60d39c40ffSdrh# logs the database connection D in using user U with password P,N.
61d39c40ffSdrh#
62d39c40ffSdrhdo_test userauth01-1.4 {
63d39c40ffSdrh  sqlite3_user_add db alice pw-4-alice 1
64d39c40ffSdrh} {SQLITE_OK}
65d39c40ffSdrhdo_test userauth01-1.5 {
66d39c40ffSdrh  execsql {
67d39c40ffSdrh    SELECT quote(x) FROM t1 ORDER BY x;
68d39c40ffSdrh    SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
69d39c40ffSdrh    SELECT name FROM sqlite_master ORDER BY name;
70d39c40ffSdrh  }
71d39c40ffSdrh} {NULL 1 2.5 'three' X'4444' alice 1 sqlite_user t1}
72d39c40ffSdrh
73570f187fSdrh# The sqlite3_user_add() interface can be used (by an admin user only)
74570f187fSdrh# to create a new user.
75570f187fSdrh#
76570f187fSdrhdo_test userauth01-1.6 {
77570f187fSdrh  sqlite3_user_add db bob pw-4-bob 0
78570f187fSdrh  sqlite3_user_add db cindy pw-4-cindy 0
79570f187fSdrh  sqlite3_user_add db david pw-4-david 0
80570f187fSdrh  execsql {
81570f187fSdrh    SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
82570f187fSdrh  }
83570f187fSdrh} {alice 1 bob 0 cindy 0 david 0}
84570f187fSdrh
85570f187fSdrh# The sqlite_user table is inaccessible (unreadable and unwriteable) to
86570f187fSdrh# non-admin users and is read-only for admin users.  However, if the same
87570f187fSdrh#
88570f187fSdrhdo_test userauth01-1.7 {
89570f187fSdrh  sqlite3 db2 test.db
90570f187fSdrh  sqlite3_user_authenticate db2 cindy pw-4-cindy
91570f187fSdrh  db2 eval {
92570f187fSdrh    SELECT quote(x) FROM t1 ORDER BY x;
93570f187fSdrh    SELECT name FROM sqlite_master ORDER BY name;
94570f187fSdrh  }
95570f187fSdrh} {NULL 1 2.5 'three' X'4444' sqlite_user t1}
96570f187fSdrhdo_test userauth01-1.8 {
97570f187fSdrh  catchsql {
98570f187fSdrh    SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
99570f187fSdrh  } db2
100570f187fSdrh} {1 {no such table: sqlite_user}}
101570f187fSdrh
102570f187fSdrh# Any user can change their own password.
103570f187fSdrh#
104570f187fSdrhdo_test userauth01-1.9 {
105570f187fSdrh  sqlite3_user_change db2 cindy xyzzy-cindy 0
106570f187fSdrh} {SQLITE_OK}
107570f187fSdrhdo_test userauth01-1.10 {
108570f187fSdrh  sqlite3_user_authenticate db2 cindy pw-4-cindy
109570f187fSdrh} {SQLITE_AUTH}
110570f187fSdrhdo_test userauth01-1.11 {
111570f187fSdrh  sqlite3_user_authenticate db2 cindy xyzzy-cindy
112570f187fSdrh} {SQLITE_OK}
1139d5b0df1Sdrhdo_test userauth01-1.12 {
1149d5b0df1Sdrh  sqlite3_user_change db alice xyzzy-alice 1
1159d5b0df1Sdrh} {SQLITE_OK}
1169d5b0df1Sdrhdo_test userauth01-1.13 {
1179d5b0df1Sdrh  sqlite3_user_authenticate db alice pw-4-alice
1189d5b0df1Sdrh} {SQLITE_AUTH}
1199d5b0df1Sdrhdo_test userauth01-1.14 {
1209d5b0df1Sdrh  sqlite3_user_authenticate db alice xyzzy-alice
1219d5b0df1Sdrh} {SQLITE_OK}
122570f187fSdrh
1239d5b0df1Sdrh# No user may change their own admin privilege setting.
1249d5b0df1Sdrh#
1259d5b0df1Sdrhdo_test userauth01-1.15 {
1269d5b0df1Sdrh  sqlite3_user_change db alice xyzzy-alice 0
1279d5b0df1Sdrh} {SQLITE_AUTH}
1289d5b0df1Sdrhdo_test userauth01-1.16 {
1299d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1309d5b0df1Sdrh} {alice 1 bob 0 cindy 0 david 0}
1319d5b0df1Sdrhdo_test userauth01-1.17 {
1329d5b0df1Sdrh  sqlite3_user_change db2 cindy xyzzy-cindy 1
1339d5b0df1Sdrh} {SQLITE_AUTH}
1349d5b0df1Sdrhdo_test userauth01-1.18 {
1359d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1369d5b0df1Sdrh} {alice 1 bob 0 cindy 0 david 0}
1379d5b0df1Sdrh
1389d5b0df1Sdrh# The sqlite3_user_change() interface can be used to change a users
1399d5b0df1Sdrh# login credentials or admin privilege.
1409d5b0df1Sdrh#
1419d5b0df1Sdrhdo_test userauth01-1.20 {
1429d5b0df1Sdrh  sqlite3_user_change db david xyzzy-david 1
1439d5b0df1Sdrh} {SQLITE_OK}
1449d5b0df1Sdrhdo_test userauth01-1.21 {
1459d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1469d5b0df1Sdrh} {alice 1 bob 0 cindy 0 david 1}
1479d5b0df1Sdrhdo_test userauth01-1.22 {
1489d5b0df1Sdrh  sqlite3_user_authenticate db2 david xyzzy-david
1499d5b0df1Sdrh} {SQLITE_OK}
1509d5b0df1Sdrhdo_test userauth01-1.23 {
1519d5b0df1Sdrh  db2 eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1529d5b0df1Sdrh} {alice 1 bob 0 cindy 0 david 1}
1539d5b0df1Sdrhdo_test userauth01-1.24 {
1549d5b0df1Sdrh  sqlite3_user_change db david pw-4-david 0
1559d5b0df1Sdrh} {SQLITE_OK}
1569d5b0df1Sdrhdo_test userauth01-1.25 {
1579d5b0df1Sdrh  sqlite3_user_authenticate db2 david pw-4-david
1589d5b0df1Sdrh} {SQLITE_OK}
1599d5b0df1Sdrhdo_test userauth01-1.26 {
1609d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1619d5b0df1Sdrh} {alice 1 bob 0 cindy 0 david 0}
1629d5b0df1Sdrhdo_test userauth01-1.27 {
1639d5b0df1Sdrh  catchsql {SELECT uname, isadmin FROM sqlite_user ORDER BY uname} db2
1649d5b0df1Sdrh} {1 {no such table: sqlite_user}}
1659d5b0df1Sdrh
1669d5b0df1Sdrh# Only an admin user can change another users login
1679d5b0df1Sdrh# credentials or admin privilege setting.
1689d5b0df1Sdrh#
1699d5b0df1Sdrhdo_test userauth01-1.30 {
1709d5b0df1Sdrh  sqlite3_user_change db2 bob xyzzy-bob 1
1719d5b0df1Sdrh} {SQLITE_AUTH}
1729d5b0df1Sdrhdo_test userauth01-1.31 {
1739d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1749d5b0df1Sdrh} {alice 1 bob 0 cindy 0 david 0}
1759d5b0df1Sdrh
1769d5b0df1Sdrh# The sqlite3_user_delete() interface can be used (by an admin user only)
1779d5b0df1Sdrh# to delete a user.
1789d5b0df1Sdrh#
1799d5b0df1Sdrhdo_test userauth01-1.40 {
1809d5b0df1Sdrh  sqlite3_user_delete db bob
1819d5b0df1Sdrh} {SQLITE_OK}
1829d5b0df1Sdrhdo_test userauth01-1.41 {
1839d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1849d5b0df1Sdrh} {alice 1 cindy 0 david 0}
1859d5b0df1Sdrhdo_test userauth01-1.42 {
1869d5b0df1Sdrh  sqlite3_user_delete db2 cindy
1879d5b0df1Sdrh} {SQLITE_AUTH}
1889d5b0df1Sdrhdo_test userauth01-1.43 {
1899d5b0df1Sdrh  sqlite3_user_delete db2 alice
1909d5b0df1Sdrh} {SQLITE_AUTH}
1919d5b0df1Sdrhdo_test userauth01-1.44 {
1929d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
1939d5b0df1Sdrh} {alice 1 cindy 0 david 0}
1949d5b0df1Sdrh
1959d5b0df1Sdrh# The currently logged-in user cannot be deleted
1969d5b0df1Sdrh#
1979d5b0df1Sdrhdo_test userauth01-1.50 {
1989d5b0df1Sdrh  sqlite3_user_delete db alice
1999d5b0df1Sdrh} {SQLITE_AUTH}
2009d5b0df1Sdrhdo_test userauth01-1.51 {
2019d5b0df1Sdrh  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
2029d5b0df1Sdrh} {alice 1 cindy 0 david 0}
203570f187fSdrh
204a000ca68Sdrh# When ATTACH-ing new database files to a connection, each newly attached
205a000ca68Sdrh# database that is an authentication-required database is checked using
206a000ca68Sdrh# the same username and password as supplied to the main database.  If that
207a000ca68Sdrh# check fails, then the ATTACH command fails with an SQLITE_AUTH error.
208a000ca68Sdrh#
209a000ca68Sdrhdo_test userauth01-1.60 {
210a000ca68Sdrh  forcedelete test3.db
211a000ca68Sdrh  sqlite3 db3 test3.db
212*7883ecfcSdrh  sqlite3_user_add db3 alice xyzzy-alice 1
213*7883ecfcSdrh} {SQLITE_OK}
214*7883ecfcSdrhdo_test userauth01-1.61 {
215a000ca68Sdrh  db3 eval {
216a000ca68Sdrh    CREATE TABLE t3(a,b,c); INSERT INTO t3 VALUES(1,2,3);
217a000ca68Sdrh    SELECT * FROM t3;
218a000ca68Sdrh  }
219a000ca68Sdrh} {1 2 3}
220a000ca68Sdrhdo_test userauth01-1.62 {
221a000ca68Sdrh  db eval {
222a000ca68Sdrh    ATTACH 'test3.db' AS aux;
223a000ca68Sdrh    SELECT * FROM t1, t3 ORDER BY x LIMIT 1;
224a000ca68Sdrh    DETACH aux;
225a000ca68Sdrh  }
226a000ca68Sdrh} {{} 1 2 3}
227a000ca68Sdrhdo_test userauth01-1.63 {
228a000ca68Sdrh  sqlite3_user_change db alice pw-4-alice 1
229a000ca68Sdrh  sqlite3_user_authenticate db alice pw-4-alice
230a000ca68Sdrh  catchsql {
231a000ca68Sdrh    ATTACH 'test3.db' AS aux;
232a000ca68Sdrh  }
233a000ca68Sdrh} {1 {unable to open database: test3.db}}
234a000ca68Sdrhdo_test userauth01-1.64 {
235a000ca68Sdrh  sqlite3_extended_errcode db
236a000ca68Sdrh} {SQLITE_AUTH}
237a000ca68Sdrhdo_test userauth01-1.65 {
238a000ca68Sdrh  db eval {PRAGMA database_list}
239a000ca68Sdrh} {~/test3.db/}
240d39c40ffSdrh
241*7883ecfcSdrh# The sqlite3_set_authorizer() callback is modified to take a 7th parameter
242*7883ecfcSdrh# which is the username of the currently logged in user, or NULL for a
243*7883ecfcSdrh# no-authentication-required database.
244*7883ecfcSdrh#
245*7883ecfcSdrhproc auth {args} {
246*7883ecfcSdrh  lappend ::authargs $args
247*7883ecfcSdrh  return SQLITE_OK
248*7883ecfcSdrh}
249*7883ecfcSdrhdo_test authuser01-2.1 {
250*7883ecfcSdrh  unset -nocomplain ::authargs
251*7883ecfcSdrh  db auth auth
252*7883ecfcSdrh  db eval {SELECT x FROM t1}
253*7883ecfcSdrh  set ::authargs
254*7883ecfcSdrh} {/SQLITE_SELECT {} {} {} {} alice/}
255*7883ecfcSdrh
256*7883ecfcSdrh
257d39c40ffSdrhfinish_test
258