xref: /sqlite-3.40.0/ext/userauth/userauth.c (revision e933b83f)
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 bulk of the implementation of the
14 ** user-authentication extension feature.  Some parts of the user-
15 ** authentication code are contained within the SQLite core (in the
16 ** src/ subdirectory of the main source code tree) but those parts
17 ** that could reasonable be separated out are moved into this file.
18 **
19 ** To compile with the user-authentication feature, append this file to
20 ** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
21 ** compile-time option.  See the user-auth.txt file in the same source
22 ** directory as this file for additional information.
23 */
24 #ifdef SQLITE_USER_AUTHENTICATION
25 #include "sqliteInt.h"
26 
27 /*
28 ** Prepare an SQL statement for use by the user authentication logic.
29 ** Return a pointer to the prepared statement on success.  Return a
30 ** NULL pointer if there is an error of any kind.
31 */
32 static sqlite3_stmt *sqlite3UserAuthPrepare(
33   sqlite3 *db,
34   const char *zFormat,
35   ...
36 ){
37   sqlite3_stmt *pStmt;
38   char *zSql;
39   int rc;
40   va_list ap;
41 
42   va_start(ap, zFormat);
43   zSql = sqlite3_vmprintf(zFormat, ap);
44   va_end(ap);
45   if( zSql==0 ) return 0;
46   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
47   sqlite3_free(zSql);
48   if( rc ){
49     sqlite3_finalize(pStmt);
50     pStmt = 0;
51   }
52   return pStmt;
53 }
54 
55 /*
56 ** Check to see if database zDb has a "sqlite_user" table and if it does
57 ** whether that table can authenticate zUser with nPw,zPw.  Write one of
58 ** the UAUTH_* user authorization level codes into *peAuth and return a
59 ** result code.
60 */
61 static int userAuthCheckLogin(
62   sqlite3 *db,               /* The database connection to check */
63   const char *zDb,           /* Name of specific database to check */
64   u8 *peAuth                 /* OUT: One of UAUTH_* constants */
65 ){
66   sqlite3_stmt *pStmt;
67   int rc;
68 
69   *peAuth = UAUTH_Unknown;
70   pStmt = sqlite3UserAuthPrepare(db,
71               "SELECT 1 FROM \"%w\".sqlite_master "
72               " WHERE name='sqlite_user' AND type='table'", zDb);
73   if( pStmt==0 ){
74     return SQLITE_NOMEM;
75   }
76   rc = sqlite3_step(pStmt);
77   sqlite3_finalize(pStmt);
78   if( rc==SQLITE_DONE ){
79     *peAuth = UAUTH_Admin;  /* No sqlite_user table.  Everybody is admin. */
80     return SQLITE_OK;
81   }
82   if( rc!=SQLITE_ROW ){
83     return rc;
84   }
85   if( db->auth.zAuthUser==0 ){
86     *peAuth = UAUTH_Fail;
87     return SQLITE_OK;
88   }
89   pStmt = sqlite3UserAuthPrepare(db,
90             "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
91             " WHERE uname=?2", zDb);
92   if( pStmt==0 ) return SQLITE_NOMEM;
93   sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
94   sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
95   rc = sqlite3_step(pStmt);
96   if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
97     *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
98   }else{
99     *peAuth = UAUTH_Fail;
100   }
101   sqlite3_finalize(pStmt);
102   return rc;
103 }
104 int sqlite3UserAuthCheckLogin(
105   sqlite3 *db,               /* The database connection to check */
106   const char *zDb,           /* Name of specific database to check */
107   u8 *peAuth                 /* OUT: One of UAUTH_* constants */
108 ){
109   int rc;
110   u8 savedAuthLevel;
111   savedAuthLevel = db->auth.authLevel;
112   db->auth.authLevel = UAUTH_Admin;
113   rc = userAuthCheckLogin(db, zDb, peAuth);
114   db->auth.authLevel = savedAuthLevel;
115   return rc;
116 }
117 
118 
119 /*
120 ** If a database contains the SQLITE_USER table, then the
121 ** sqlite3_user_authenticate() interface must be invoked with an
122 ** appropriate username and password prior to enable read and write
123 ** access to the database.
124 **
125 ** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
126 ** combination is incorrect or unknown.
127 **
128 ** If the SQLITE_USER table is not present in the database file, then
129 ** this interface is a harmless no-op returnning SQLITE_OK.
130 */
131 int sqlite3_user_authenticate(
132   sqlite3 *db,           /* The database connection */
133   const char *zUsername, /* Username */
134   int nPW,               /* Number of bytes in aPW[] */
135   const char *zPW        /* Password or credentials */
136 ){
137   int rc;
138   u8 authLevel = UAUTH_Fail;
139   db->auth.authLevel = UAUTH_Unknown;
140   sqlite3_free(db->auth.zAuthUser);
141   sqlite3_free(db->auth.zAuthPW);
142   memset(&db->auth, 0, sizeof(db->auth));
143   db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
144   if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
145   db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
146   if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
147   memcpy(db->auth.zAuthPW,zPW,nPW);
148   db->auth.nAuthPW = nPW;
149   rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
150   db->auth.authLevel = authLevel;
151   if( rc ){
152     return rc;           /* OOM error, I/O error, etc. */
153   }
154   if( authLevel<UAUTH_User ){
155     return SQLITE_AUTH;  /* Incorrect username and/or password */
156   }
157   return SQLITE_OK;      /* Successful login */
158 }
159 
160 /*
161 ** The sqlite3_user_add() interface can be used (by an admin user only)
162 ** to create a new user.  When called on a no-authentication-required
163 ** database, this routine converts the database into an authentication-
164 ** required database, automatically makes the added user an
165 ** administrator, and logs in the current connection as that user.
166 ** The sqlite3_user_add() interface only works for the "main" database, not
167 ** for any ATTACH-ed databases.  Any call to sqlite3_user_add() by a
168 ** non-admin user results in an error.
169 */
170 int sqlite3_user_add(
171   sqlite3 *db,           /* Database connection */
172   const char *zUsername, /* Username to be added */
173   int isAdmin,           /* True to give new user admin privilege */
174   int nPW,               /* Number of bytes in aPW[] */
175   const void *aPW        /* Password or credentials */
176 ){
177   if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
178   return SQLITE_OK;
179 }
180 
181 /*
182 ** The sqlite3_user_change() interface can be used to change a users
183 ** login credentials or admin privilege.  Any user can change their own
184 ** login credentials.  Only an admin user can change another users login
185 ** credentials or admin privilege setting.  No user may change their own
186 ** admin privilege setting.
187 */
188 int sqlite3_user_change(
189   sqlite3 *db,           /* Database connection */
190   const char *zUsername, /* Username to change */
191   int isAdmin,           /* Modified admin privilege for the user */
192   int nPW,               /* Number of bytes in aPW[] */
193   const void *aPW        /* Modified password or credentials */
194 ){
195   if( db->auth.authLevel<UAUTH_User ) return SQLITE_ERROR;
196   if( strcmp(db->auth.zAuthUser, zUsername)!=0
197        && db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
198   return SQLITE_OK;
199 }
200 
201 /*
202 ** The sqlite3_user_delete() interface can be used (by an admin user only)
203 ** to delete a user.  The currently logged-in user cannot be deleted,
204 ** which guarantees that there is always an admin user and hence that
205 ** the database cannot be converted into a no-authentication-required
206 ** database.
207 */
208 int sqlite3_user_delete(
209   sqlite3 *db,           /* Database connection */
210   const char *zUsername  /* Username to remove */
211 ){
212   if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
213   return SQLITE_OK;
214 }
215 
216 #endif /* SQLITE_USER_AUTHENTICATION */
217