Skip to content

Commit 3586f98

Browse files
author
drh
committed
Add the SQLITE_USER_AUTHENTICATION extension to the trunk. This extension
is disabled by default. Special compilation procedures are need to enable it. FossilOrigin-Name: 65884d4f81a4705b0356b6cb8ec4909945ff5c19
2 parents 524a733 + c891c6c commit 3586f98

30 files changed

+1397
-193
lines changed

ext/userauth/sqlite3userauth.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
** 2014-09-08
3+
**
4+
** The author disclaims copyright to this source code. In place of
5+
** a legal notice, here is a blessing:
6+
**
7+
** May you do good and not evil.
8+
** May you find forgiveness for yourself and forgive others.
9+
** May you share freely, never taking more than you give.
10+
**
11+
*************************************************************************
12+
**
13+
** This file contains the application interface definitions for the
14+
** user-authentication extension feature.
15+
**
16+
** To compile with the user-authentication feature, append this file to
17+
** end of an SQLite amalgamation header file ("sqlite3.h"), then add
18+
** the SQLITE_USER_AUTHENTICATION compile-time option. See the
19+
** user-auth.txt file in the same source directory as this file for
20+
** additional information.
21+
*/
22+
#ifdef SQLITE_USER_AUTHENTICATION
23+
24+
/*
25+
** If a database contains the SQLITE_USER table, then the
26+
** sqlite3_user_authenticate() interface must be invoked with an
27+
** appropriate username and password prior to enable read and write
28+
** access to the database.
29+
**
30+
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
31+
** combination is incorrect or unknown.
32+
**
33+
** If the SQLITE_USER table is not present in the database file, then
34+
** this interface is a harmless no-op returnning SQLITE_OK.
35+
*/
36+
int sqlite3_user_authenticate(
37+
sqlite3 *db, /* The database connection */
38+
const char *zUsername, /* Username */
39+
const char *aPW, /* Password or credentials */
40+
int nPW /* Number of bytes in aPW[] */
41+
);
42+
43+
/*
44+
** The sqlite3_user_add() interface can be used (by an admin user only)
45+
** to create a new user. When called on a no-authentication-required
46+
** database, this routine converts the database into an authentication-
47+
** required database, automatically makes the added user an
48+
** administrator, and logs in the current connection as that user.
49+
** The sqlite3_user_add() interface only works for the "main" database, not
50+
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
51+
** non-admin user results in an error.
52+
*/
53+
int sqlite3_user_add(
54+
sqlite3 *db, /* Database connection */
55+
const char *zUsername, /* Username to be added */
56+
const char *aPW, /* Password or credentials */
57+
int nPW, /* Number of bytes in aPW[] */
58+
int isAdmin /* True to give new user admin privilege */
59+
);
60+
61+
/*
62+
** The sqlite3_user_change() interface can be used to change a users
63+
** login credentials or admin privilege. Any user can change their own
64+
** login credentials. Only an admin user can change another users login
65+
** credentials or admin privilege setting. No user may change their own
66+
** admin privilege setting.
67+
*/
68+
int sqlite3_user_change(
69+
sqlite3 *db, /* Database connection */
70+
const char *zUsername, /* Username to change */
71+
const char *aPW, /* New password or credentials */
72+
int nPW, /* Number of bytes in aPW[] */
73+
int isAdmin /* Modified admin privilege for the user */
74+
);
75+
76+
/*
77+
** The sqlite3_user_delete() interface can be used (by an admin user only)
78+
** to delete a user. The currently logged-in user cannot be deleted,
79+
** which guarantees that there is always an admin user and hence that
80+
** the database cannot be converted into a no-authentication-required
81+
** database.
82+
*/
83+
int sqlite3_user_delete(
84+
sqlite3 *db, /* Database connection */
85+
const char *zUsername /* Username to remove */
86+
);
87+
88+
#endif /* SQLITE_USER_AUTHENTICATION */

ext/userauth/user-auth.txt

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
Activate the user authentication logic by including the
2+
ext/userauth/userauth.c source code file in the build and
3+
adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
4+
The ext/userauth/sqlite3userauth.h header file is available to
5+
applications to define the interface.
6+
7+
When using the SQLite amalgamation, it is sufficient to append
8+
the ext/userauth/userauth.c source file onto the end of the
9+
amalgamation.
10+
11+
The following new APIs are available when user authentication is
12+
activated:
13+
14+
int sqlite3_user_authenticate(
15+
sqlite3 *db, /* The database connection */
16+
const char *zUsername, /* Username */
17+
const char *aPW, /* Password or credentials */
18+
int nPW /* Number of bytes in aPW[] */
19+
);
20+
21+
int sqlite3_user_add(
22+
sqlite3 *db, /* Database connection */
23+
const char *zUsername, /* Username to be added */
24+
const char *aPW, /* Password or credentials */
25+
int nPW, /* Number of bytes in aPW[] */
26+
int isAdmin /* True to give new user admin privilege */
27+
);
28+
29+
int sqlite3_user_change(
30+
sqlite3 *db, /* Database connection */
31+
const char *zUsername, /* Username to change */
32+
const void *aPW, /* Modified password or credentials */
33+
int nPW, /* Number of bytes in aPW[] */
34+
int isAdmin /* Modified admin privilege for the user */
35+
);
36+
37+
int sqlite3_user_delete(
38+
sqlite3 *db, /* Database connection */
39+
const char *zUsername /* Username to remove */
40+
);
41+
42+
With this extension, a database can be marked as requiring authentication.
43+
By default a database does not require authentication.
44+
45+
The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
46+
work as before: they open a new database connection. However, if the
47+
database being opened requires authentication, then attempts to read
48+
or write from the database will fail with an SQLITE_AUTH error until
49+
after sqlite3_user_authenticate() has been called successfully. The
50+
sqlite3_user_authenticate() call will return SQLITE_OK if the
51+
authentication credentials are accepted and SQLITE_ERROR if not.
52+
53+
Calling sqlite3_user_authenticate() on a no-authentication-required
54+
database connection is a harmless no-op.
55+
56+
If the database is encrypted, then sqlite3_key_v2() must be called first,
57+
with the correct decryption key, prior to invoking sqlite3_user_authenticate().
58+
59+
To recapitulate: When opening an existing unencrypted authentication-
60+
required database, the call sequence is:
61+
62+
sqlite3_open_v2()
63+
sqlite3_user_authenticate();
64+
/* Database is now usable */
65+
66+
To open an existing, encrypted, authentication-required database, the
67+
call sequence is:
68+
69+
sqlite3_open_v2();
70+
sqlite3_key_v2();
71+
sqlite3_user_authenticate();
72+
/* Database is now usable */
73+
74+
When opening a no-authentication-required database, the database
75+
connection is treated as if it was authenticated as an admin user.
76+
77+
When ATTACH-ing new database files to a connection, each newly attached
78+
database that is an authentication-required database is checked using
79+
the same username and password as supplied to the main database. If that
80+
check fails, then the ATTACH command fails with an SQLITE_AUTH error.
81+
82+
The sqlite3_user_add() interface can be used (by an admin user only)
83+
to create a new user. When called on a no-authentication-required
84+
database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
85+
converts the database into an authentication-required database and
86+
logs in the database connection D as user U with password P,N.
87+
To convert a no-authentication-required database into an authentication-
88+
required database, the isAdmin parameter must be true. If
89+
sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
90+
database and A is false, then the call fails with an SQLITE_AUTH error.
91+
92+
Any call to sqlite3_user_add() by a non-admin user results in an error.
93+
94+
Hence, to create a new, unencrypted, authentication-required database,
95+
the call sequence is:
96+
97+
sqlite3_open_v2();
98+
sqlite3_user_add();
99+
100+
And to create a new, encrypted, authentication-required database, the call
101+
sequence is:
102+
103+
sqlite3_open_v2();
104+
sqlite3_key_v2();
105+
sqlite3_user_add();
106+
107+
The sqlite3_user_delete() interface can be used (by an admin user only)
108+
to delete a user. The currently logged-in user cannot be deleted,
109+
which guarantees that there is always an admin user and hence that
110+
the database cannot be converted into a no-authentication-required
111+
database.
112+
113+
The sqlite3_user_change() interface can be used to change a users
114+
login credentials or admin privilege. Any user can change their own
115+
password. Only an admin user can change another users login
116+
credentials or admin privilege setting. No user may change their own
117+
admin privilege setting.
118+
119+
The sqlite3_set_authorizer() callback is modified to take a 7th parameter
120+
which is the username of the currently logged in user, or NULL for a
121+
no-authentication-required database.
122+
123+
-----------------------------------------------------------------------------
124+
Implementation notes:
125+
126+
An authentication-required database is identified by the presence of a
127+
new table:
128+
129+
CREATE TABLE sqlite_user(
130+
uname TEXT PRIMARY KEY,
131+
isAdmin BOOLEAN,
132+
pw BLOB
133+
) WITHOUT ROWID;
134+
135+
The sqlite_user table is inaccessible (unreadable and unwriteable) to
136+
non-admin users and is read-only for admin users. However, if the same
137+
database file is opened by a version of SQLite that omits
138+
the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
139+
table will be readable by anybody and writeable by anybody if
140+
the "PRAGMA writable_schema=ON" statement is run first.
141+
142+
The sqlite_user.pw field is encoded by a built-in SQL function
143+
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
144+
is the plaintext password supplied to the sqlite3_user_authenticate()
145+
interface. The second argument is the sqlite_user.pw value and is supplied
146+
so that the function can extract the "salt" used by the password encoder.
147+
The result of sqlite_crypt(X,Y) is another blob which is the value that
148+
ends up being stored in sqlite_user.pw. To verify credentials X supplied
149+
by the sqlite3_user_authenticate() routine, SQLite runs:
150+
151+
sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
152+
153+
To compute an appropriate sqlite_user.pw value from a new or modified
154+
password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
155+
when the second argument is NULL.
156+
157+
The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
158+
which prevents passwords from being revealed by searching the raw database
159+
for ASCII text, but is otherwise trivally broken. For better password
160+
security, the database should be encrypted using the SQLite Encryption
161+
Extension or similar technology. Or, the application can use the
162+
sqlite3_create_function() interface to provide an alternative
163+
implementation of sqlite_crypt() that computes a stronger password hash,
164+
perhaps using a cryptographic hash function like SHA1.

0 commit comments

Comments
 (0)