SQLite

Check-in [c8171ecd0d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Further ideas on user authentication. Not yet working code.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | user-auth
Files: files | file ages | folders
SHA1: c8171ecd0d6f097c9e95d5f6643bae8d67f44750
User & Date: drh 2014-09-10 17:34:28.937
Context
2014-09-10
19:01
Add the ".user" shell command and implement the sqlite3_user_add() routine. Incremental check-in. The code compiles but does not work. (check-in: a0455f9deb user: drh tags: user-auth)
17:34
Further ideas on user authentication. Not yet working code. (check-in: c8171ecd0d user: drh tags: user-auth)
2014-09-09
14:47
Non-working preliminary implementation attempts on user authentication. (check-in: 8440f093ba user: drh tags: user-auth)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/userauth/userauth.c.
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79


80
81
82
83

84
85
86
87




88
89
90
91
92
93
94
95
96
97


98
99
100
101














102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127


128
129
130
131
132
133
134
135
136

137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179



180
181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
**
** To compile with the user-authentication feature, append this file to
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
** compile-time option.  See the user-auth.txt file in the same source
** directory as this file for additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION


/*
** Prepare an SQL statement for use by the user authentication logic.
** Return a pointer to the prepared statement on success.  Return a
** NULL pointer if there is an error of any kind.
*/
static sqlite3_stmt *sqlite3UserAuthPrepare(
  sqlite3 *db,
  const char *zFormat,
  ...
){
  sqlite3_stmt *pStmt;
  char *zSql;
  int rc;
  va_list ap;

  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( zSql==0 ) return 0;
  savedFlags = db->auth.authFlags;
  db->auth.authFlags |= UAUTH_Ovrd;
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  db->auth.authFlags = savedFlags;
  sqlite3_free(zSql);
  if( rc ){
    sqlite3_finalize(pStmt);
    pStmt = 0;
  }
  return pStmt;
}

/*
** Check to see if database zDb has a "sqlite_user" table and if it does
** whether that table can authenticate zUser with nPw,zPw.  


*/
static int sqlite3UserAuthCheckLogin(
  sqlite3 *db,               /* The database connection to check */
  const char *zDb,           /* Name of specific database to check */
  const char *zUser,         /* User name */
  int nPw,                   /* Size of password in bytes */
  const char *zPw,           /* Password */
  int *pbOk                  /* OUT: write boolean result here */
){
  sqlite3_stmt *pStmt;
  char *zSql;
  int rc;
  int iResult;

  *pbOk = 0;
  iResult = 0;
  pStmt = sqlite3UserAuthPrepare(db, 
              "SELECT 1 FROM \"%w\".sqlite_master "
              " WHERE name='sqlite_user' AND type='table'", zDb);
  if( pStmt==0 ) return SQLITE_NOMEM;


  rc = sqlite3_step(pStmt):
  sqlite3_finalize(pStmt);
  if( rc==SQLITE_DONE ){
    *pbOk = 1;

    return SQLITE_OK;
  }
  if( rc!=SQLITE_OK ){
    return rc;




  }
  pStmt = sqlite3UserAuthPrepare(db,
            "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
            " WHERE uname=?2", zDb);
  if( pStmt==0 ) return SQLITE_NOMEM;
  sqlite3_bind_blob(pStmt, 1, zPw, nPw, SQLITE_STATIC);
  sqlite3_bind_text(pStmt, 2, zUser, -1, SQLITE_STATIC);
  rc = sqlite_step(pStmt);
  if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
    *pbOk = sqlite3_column_int(pStmt, 1);


  }
  sqlite3_finalize(pStmt);
  return rc;
}















/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
** appropriate username and password prior to enable read and write
** access to the database.
**
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
** combination is incorrect or unknown.
**
** If the SQLITE_USER table is not present in the database file, then
** this interface is a harmless no-op returnning SQLITE_OK.
*/
int sqlite3_user_authenticate(
  sqlite3 *db,           /* The database connection */
  const char *zUsername, /* Username */
  int nPW,               /* Number of bytes in aPW[] */
  const void *aPW        /* Password or credentials */
){
  int bOk = 0;
  int rc;

  rc = sqlite3UserAuthCheckLogin(db, zUsername, nPw, zPw, &bOk);
  if( bOk ){
    db->auth.authFlags = bOk==2 ? UAUTH_Auth|UAUTH_Admin : UAUTH_Auth;
    sqlite3_free(db->auth.zAuthUser);


    db->auth.zAuthUser = sqlite3_malloc("%s", zUsername);
    sqlite3_free(db->auth.zPw);
    db->auth.zPw = sqlite3_malloc( nPw+1 );
    if( db->auth.zPw ){
      memcpy(db->auth.zPw,zPw,nPw);
      db->auth.nPw = nPw;
      rc = SQLITE_OK;
    }else{
      rc = SQLITE_NOMEM;

    }
  }else{
    db->auth.authFlags = 0;

  }
  return rc;
}

/*
** The sqlite3_user_add() interface can be used (by an admin user only)
** to create a new user.  When called on a no-authentication-required
** database, this routine converts the database into an authentication-
** required database, automatically makes the added user an
** administrator, and logs in the current connection as that user.
** The sqlite3_user_add() interface only works for the "main" database, not
** for any ATTACH-ed databases.  Any call to sqlite3_user_add() by a
** non-admin user results in an error.
*/
int sqlite3_user_add(
  sqlite3 *db,           /* Database connection */
  const char *zUsername, /* Username to be added */
  int isAdmin,           /* True to give new user admin privilege */
  int nPW,               /* Number of bytes in aPW[] */
  const void *aPW        /* Password or credentials */
){
  if( !DbIsAdmin(db) ) return SQLITE_ERROR;
  
  return SQLITE_OK;
}

/*
** The sqlite3_user_change() interface can be used to change a users
** login credentials or admin privilege.  Any user can change their own
** login credentials.  Only an admin user can change another users login
** credentials or admin privilege setting.  No user may change their own 
** admin privilege setting.
*/
int sqlite3_user_change(
  sqlite3 *db,           /* Database connection */
  const char *zUsername, /* Username to change */
  int isAdmin,           /* Modified admin privilege for the user */
  int nPW,               /* Number of bytes in aPW[] */
  const void *aPW        /* Modified password or credentials */
){



  return SQLITE_OK;
}

/*
** The sqlite3_user_delete() interface can be used (by an admin user only)
** to delete a user.  The currently logged-in user cannot be deleted,
** which guarantees that there is always an admin user and hence that
** the database cannot be converted into a no-authentication-required
** database.
*/
int sqlite3_user_delete(
  sqlite3 *db,           /* Database connection */
  const char *zUsername  /* Username to remove */
){

  return SQLITE_OK;
}

#endif /* SQLITE_USER_AUTHENTICATION */







>




















<
<

<










|
>
>

|


<
<
<
|


<

<

|
<



|
>
>
|


<
>


|

>
>
>
>





|
|
|

|
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>

















|

<

|
<
<
|
|
>
>
|
|
|
|
|
|
|
|
|
>
|
<
|
>

|



















|
<

















>
>
>














>




18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45


46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63



64
65
66

67

68
69

70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
**
** To compile with the user-authentication feature, append this file to
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
** compile-time option.  See the user-auth.txt file in the same source
** directory as this file for additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
#include "sqliteInt.h"

/*
** Prepare an SQL statement for use by the user authentication logic.
** Return a pointer to the prepared statement on success.  Return a
** NULL pointer if there is an error of any kind.
*/
static sqlite3_stmt *sqlite3UserAuthPrepare(
  sqlite3 *db,
  const char *zFormat,
  ...
){
  sqlite3_stmt *pStmt;
  char *zSql;
  int rc;
  va_list ap;

  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( zSql==0 ) return 0;


  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);

  sqlite3_free(zSql);
  if( rc ){
    sqlite3_finalize(pStmt);
    pStmt = 0;
  }
  return pStmt;
}

/*
** Check to see if database zDb has a "sqlite_user" table and if it does
** whether that table can authenticate zUser with nPw,zPw.  Write one of
** the UAUTH_* user authorization level codes into *peAuth and return a
** result code.
*/
static int userAuthCheckLogin(
  sqlite3 *db,               /* The database connection to check */
  const char *zDb,           /* Name of specific database to check */



  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
){
  sqlite3_stmt *pStmt;

  int rc;


  *peAuth = UAUTH_Unknown;

  pStmt = sqlite3UserAuthPrepare(db, 
              "SELECT 1 FROM \"%w\".sqlite_master "
              " WHERE name='sqlite_user' AND type='table'", zDb);
  if( pStmt==0 ){
    return SQLITE_NOMEM;
  }
  rc = sqlite3_step(pStmt);
  sqlite3_finalize(pStmt);
  if( rc==SQLITE_DONE ){

    *peAuth = UAUTH_Admin;  /* No sqlite_user table.  Everybody is admin. */
    return SQLITE_OK;
  }
  if( rc!=SQLITE_ROW ){
    return rc;
  }
  if( db->auth.zAuthUser==0 ){
    *peAuth = UAUTH_Fail;
    return SQLITE_OK;
  }
  pStmt = sqlite3UserAuthPrepare(db,
            "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
            " WHERE uname=?2", zDb);
  if( pStmt==0 ) return SQLITE_NOMEM;
  sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
  sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
  rc = sqlite3_step(pStmt);
  if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
    *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
  }else{
    *peAuth = UAUTH_Fail;
  }
  sqlite3_finalize(pStmt);
  return rc;
}
int sqlite3UserAuthCheckLogin(
  sqlite3 *db,               /* The database connection to check */
  const char *zDb,           /* Name of specific database to check */
  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
){
  int rc;
  u8 savedAuthLevel;
  savedAuthLevel = db->auth.authLevel;
  db->auth.authLevel = UAUTH_Admin;
  rc = userAuthCheckLogin(db, zDb, peAuth);
  db->auth.authLevel = savedAuthLevel;
  return rc;
}


/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
** appropriate username and password prior to enable read and write
** access to the database.
**
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
** combination is incorrect or unknown.
**
** If the SQLITE_USER table is not present in the database file, then
** this interface is a harmless no-op returnning SQLITE_OK.
*/
int sqlite3_user_authenticate(
  sqlite3 *db,           /* The database connection */
  const char *zUsername, /* Username */
  int nPW,               /* Number of bytes in aPW[] */
  const char *zPW        /* Password or credentials */
){

  int rc;
  u8 authLevel = UAUTH_Fail;


  db->auth.authLevel = UAUTH_Unknown;
  sqlite3_free(db->auth.zAuthUser);
  sqlite3_free(db->auth.zAuthPW);
  memset(&db->auth, 0, sizeof(db->auth));
  db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
  if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
  db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
  if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
  memcpy(db->auth.zAuthPW,zPW,nPW);
  db->auth.nAuthPW = nPW;
  rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
  db->auth.authLevel = authLevel;
  if( rc ){
    return rc;           /* OOM error, I/O error, etc. */
  }

  if( authLevel<UAUTH_User ){
    return SQLITE_AUTH;  /* Incorrect username and/or password */
  }
  return SQLITE_OK;      /* Successful login */
}

/*
** The sqlite3_user_add() interface can be used (by an admin user only)
** to create a new user.  When called on a no-authentication-required
** database, this routine converts the database into an authentication-
** required database, automatically makes the added user an
** administrator, and logs in the current connection as that user.
** The sqlite3_user_add() interface only works for the "main" database, not
** for any ATTACH-ed databases.  Any call to sqlite3_user_add() by a
** non-admin user results in an error.
*/
int sqlite3_user_add(
  sqlite3 *db,           /* Database connection */
  const char *zUsername, /* Username to be added */
  int isAdmin,           /* True to give new user admin privilege */
  int nPW,               /* Number of bytes in aPW[] */
  const void *aPW        /* Password or credentials */
){
  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;

  return SQLITE_OK;
}

/*
** The sqlite3_user_change() interface can be used to change a users
** login credentials or admin privilege.  Any user can change their own
** login credentials.  Only an admin user can change another users login
** credentials or admin privilege setting.  No user may change their own 
** admin privilege setting.
*/
int sqlite3_user_change(
  sqlite3 *db,           /* Database connection */
  const char *zUsername, /* Username to change */
  int isAdmin,           /* Modified admin privilege for the user */
  int nPW,               /* Number of bytes in aPW[] */
  const void *aPW        /* Modified password or credentials */
){
  if( db->auth.authLevel<UAUTH_User ) return SQLITE_ERROR;
  if( strcmp(db->auth.zAuthUser, zUsername)!=0
       && db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
  return SQLITE_OK;
}

/*
** The sqlite3_user_delete() interface can be used (by an admin user only)
** to delete a user.  The currently logged-in user cannot be deleted,
** which guarantees that there is always an admin user and hence that
** the database cannot be converted into a no-authentication-required
** database.
*/
int sqlite3_user_delete(
  sqlite3 *db,           /* Database connection */
  const char *zUsername  /* Username to remove */
){
  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
  return SQLITE_OK;
}

#endif /* SQLITE_USER_AUTHENTICATION */
Changes to main.mk.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
         main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         memjournal.o \
         mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
         notify.o opcodes.o os.o os_unix.o os_win.o \
         pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
         random.o resolve.o rowset.o rtree.o select.o status.o \
         table.o threads.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
	 vdbetrace.o wal.o walker.o where.o utf.o vtab.o



# All of the source code files.
#







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
         main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         memjournal.o \
         mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
         notify.o opcodes.o os.o os_unix.o os_win.o \
         pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
         random.o resolve.o rowset.o rtree.o select.o status.o \
         table.o threads.o tokenize.o trigger.o \
         update.o userauth.o util.o vacuum.o \
         vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
	 vdbetrace.o wal.o walker.o where.o utf.o vtab.o



# All of the source code files.
#
210
211
212
213
214
215
216
217


218
219
220
221
222
223
224
SRC += \
  $(TOP)/ext/icu/sqliteicu.h \
  $(TOP)/ext/icu/icu.c
SRC += \
  $(TOP)/ext/rtree/sqlite3rtree.h \
  $(TOP)/ext/rtree/rtree.h \
  $(TOP)/ext/rtree/rtree.c




# Generated source code files
#
SRC += \
  keywordhash.h \
  opcodes.c \
  opcodes.h \







|
>
>







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
SRC += \
  $(TOP)/ext/icu/sqliteicu.h \
  $(TOP)/ext/icu/icu.c
SRC += \
  $(TOP)/ext/rtree/sqlite3rtree.h \
  $(TOP)/ext/rtree/rtree.h \
  $(TOP)/ext/rtree/rtree.c
SRC += \
  $(TOP)/ext/userauth/userauth.c \
  $(TOP)/ext/userauth/userauth.h

# Generated source code files
#
SRC += \
  keywordhash.h \
  opcodes.c \
  opcodes.h \
373
374
375
376
377
378
379


380
381
382
383
384
385
386
  $(TOP)/ext/fts3/fts3Int.h \
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_tokenizer.h
EXTHDR += \
  $(TOP)/ext/rtree/rtree.h
EXTHDR += \
  $(TOP)/ext/icu/sqliteicu.h



# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	sqlite3.h libsqlite3.a sqlite3$(EXE)

libsqlite3.a:	$(LIBOBJ)







>
>







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  $(TOP)/ext/fts3/fts3Int.h \
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_tokenizer.h
EXTHDR += \
  $(TOP)/ext/rtree/rtree.h
EXTHDR += \
  $(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
  $(TOP)/ext/userauth/userauth.h

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	sqlite3.h libsqlite3.a sqlite3$(EXE)

libsqlite3.a:	$(LIBOBJ)
553
554
555
556
557
558
559



560
561
562
563
564
565
566
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

fts3_write.o:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c

rtree.o:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c





# Rules for building test programs and for running tests
#
tclsqlite3:	$(TOP)/src/tclsqlite.c libsqlite3.a
	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
		$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)







>
>
>







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

fts3_write.o:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c

rtree.o:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c

userauth.o:	$(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c


# Rules for building test programs and for running tests
#
tclsqlite3:	$(TOP)/src/tclsqlite.c libsqlite3.a
	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
		$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)
Changes to src/build.c.
298
299
300
301
302
303
304
305


306
307
308
309
310
311
312
  int i;
  assert( zName!=0 );
  /* All mutexes are required for schema access.  Make sure we hold them. */
  assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
#if SQLITE_USER_AUTHENTICATION
  /* Only the admin user is allowed to know that the sqlite_user table
  ** exists */
  if( DbIsAdmin(db)==0 && sqlite3UserAuthTable(zName)!=0 ) return 0;


#endif
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
    if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
    assert( sqlite3SchemaMutexHeld(db, j, 0) );
    p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
    if( p ) break;







|
>
>







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  int i;
  assert( zName!=0 );
  /* All mutexes are required for schema access.  Make sure we hold them. */
  assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
#if SQLITE_USER_AUTHENTICATION
  /* Only the admin user is allowed to know that the sqlite_user table
  ** exists */
  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
    return 0;
  }
#endif
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
    if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
    assert( sqlite3SchemaMutexHeld(db, j, 0) );
    p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
    if( p ) break;
344
345
346
347
348
349
350






351
352
353
354
355
356
357
    if( zDbase ){
      sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
    }else{
      sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
    }
    pParse->checkSchema = 1;
  }






  return p;
}

/*
** Locate the table identified by *p.
**
** This is a wrapper around sqlite3LocateTable(). The difference between







>
>
>
>
>
>







346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
    if( zDbase ){
      sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
    }else{
      sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
    }
    pParse->checkSchema = 1;
  }
#if SQLITE_USER_AUTHENICATION
  else if( pParse->db->auth.authLevel<UAUTH_User ){
    sqlite3ErrorMsg(pParse, "user not authenticated");
    p = 0;
  }
#endif
  return p;
}

/*
** Locate the table identified by *p.
**
** This is a wrapper around sqlite3LocateTable(). The difference between
Changes to src/main.c.
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
    }
    sqlite3Error(db, rc);
    goto opendb_out;
  }
  db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
  db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);

#if SQLITE_USER_AUTHENTICATION
  db->auth.authFlags = UAUTH_Auth|UAUTH_Admin;
#endif

  /* The default safety_level for the main database is 'full'; for the temp
  ** database it is 'NONE'. This matches the pager layer defaults.  
  */
  db->aDb[0].zName = "main";
  db->aDb[0].safety_level = 3;
  db->aDb[1].zName = "temp";
  db->aDb[1].safety_level = 1;







<
<
<
<







2566
2567
2568
2569
2570
2571
2572




2573
2574
2575
2576
2577
2578
2579
    }
    sqlite3Error(db, rc);
    goto opendb_out;
  }
  db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
  db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);





  /* The default safety_level for the main database is 'full'; for the temp
  ** database it is 'NONE'. This matches the pager layer defaults.  
  */
  db->aDb[0].zName = "main";
  db->aDb[0].safety_level = 3;
  db->aDb[1].zName = "temp";
  db->aDb[1].safety_level = 1;
Changes to src/pragma.c.
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
      int mask = aPragmaNames[mid].iArg;    /* Mask of bits to set or clear. */
      if( db->autoCommit==0 ){
        /* Foreign key support may not be enabled or disabled while not
        ** in auto-commit mode.  */
        mask &= ~(SQLITE_ForeignKeys);
      }
#if SQLITE_USER_AUTHENTICATION
      if( !DbIsAdmin(db) ){
        /* Do not allow non-admin users to modify the schema arbitrarily */
        mask &= ~(SQLITE_WriteSchema);
      }
#endif

      if( sqlite3GetBoolean(zRight, 0) ){
        db->flags |= mask;







|







1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
      int mask = aPragmaNames[mid].iArg;    /* Mask of bits to set or clear. */
      if( db->autoCommit==0 ){
        /* Foreign key support may not be enabled or disabled while not
        ** in auto-commit mode.  */
        mask &= ~(SQLITE_ForeignKeys);
      }
#if SQLITE_USER_AUTHENTICATION
      if( db->auth.authLevel<UAUTH_Admin ){
        /* Do not allow non-admin users to modify the schema arbitrarily */
        mask &= ~(SQLITE_WriteSchema);
      }
#endif

      if( sqlite3GetBoolean(zRight, 0) ){
        db->flags |= mask;
Changes to src/prepare.c.
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    rc = initData.rc;
    goto error_out;
  }
  pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
  if( ALWAYS(pTab) ){
    pTab->tabFlags |= TF_Readonly;
  }
#if SQLITE_USER_AUTHENTICATION
  db->auth.authFlags = UAUTH_Auth|UAUTH_Admin;
#endif

  /* Create a cursor to hold the database open
  */
  pDb = &db->aDb[iDb];
  if( pDb->pBt==0 ){
    if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
      DbSetProperty(db, 1, DB_SchemaLoaded);







<
<
<







202
203
204
205
206
207
208



209
210
211
212
213
214
215
    rc = initData.rc;
    goto error_out;
  }
  pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
  if( ALWAYS(pTab) ){
    pTab->tabFlags |= TF_Readonly;
  }




  /* Create a cursor to hold the database open
  */
  pDb = &db->aDb[iDb];
  if( pDb->pBt==0 ){
    if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
    ** of the schema was loaded before the error occurred. The primary
    ** purpose of this is to allow access to the sqlite_master table
    ** even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE_OK;
  }
#if SQLITE_USER_AUTHENTICATION
  if( rc==SQLITE_OK && iDb!=1 ){
    if( sqlite3FindTable(db, "sqlite_user", db->aDb[iDb].zName)!=0 ){
      db->auth.authFlags = UAUTH_AuthReqd;
    }
  }
#endif


  /* Jump here for an error that occurs after successfully allocating
  ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
  ** before that point, jump to error_out.
  */
initone_error_out:
  if( openedTransaction ){







<
<
<
<
<
<
<
<







357
358
359
360
361
362
363








364
365
366
367
368
369
370
    ** of the schema was loaded before the error occurred. The primary
    ** purpose of this is to allow access to the sqlite_master table
    ** even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE_OK;
  }









  /* Jump here for an error that occurs after successfully allocating
  ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
  ** before that point, jump to error_out.
  */
initone_error_out:
  if( openedTransaction ){
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  }

  /* Once all the other databases have been initialized, load the schema
  ** for the TEMP database. This is loaded last, as the TEMP database
  ** schema may contain references to objects in other databases.
  */
#ifndef SQLITE_OMIT_TEMPDB
  if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
                    && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
    rc = sqlite3InitOne(db, 1, pzErrMsg);
    if( rc ){
      sqlite3ResetOneSchema(db, 1);
    }
  }
#endif








|
|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  }

  /* Once all the other databases have been initialized, load the schema
  ** for the TEMP database. This is loaded last, as the TEMP database
  ** schema may contain references to objects in other databases.
  */
#ifndef SQLITE_OMIT_TEMPDB
  assert( db->nDb>1 );
  if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
    rc = sqlite3InitOne(db, 1, pzErrMsg);
    if( rc ){
      sqlite3ResetOneSchema(db, 1);
    }
  }
#endif

721
722
723
724
725
726
727














728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  int rc;
  assert( ppStmt!=0 );
  *ppStmt = 0;
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);














  sqlite3BtreeEnterAll(db);
  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  if( rc==SQLITE_SCHEMA ){
    sqlite3_finalize(*ppStmt);
    rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  }
#if SQLITE_USER_AUTHENTICATION
  assert( rc==SQLITE_OK || *ppStmt==0 );
printf("rc=%d init=%d auth=%d sql=[%.50s]\n", rc, db->init.busy, db->auth.authFlags, zSql);
fflush(stdout);
  if( rc==SQLITE_OK && !DbIsAuth(db) && db->init.busy==0 ){
    sqlite3_finalize(*ppStmt);
    *ppStmt = 0;
    sqlite3ErrorWithMsg(db, SQLITE_ERROR, "user not authenticated");
    rc = SQLITE_ERROR;
  }
#endif
  sqlite3BtreeLeaveAll(db);
  sqlite3_mutex_leave(db->mutex);
  assert( rc==SQLITE_OK || *ppStmt==0 );
  return rc;
}

/*







>
>
>
>
>
>
>
>
>
>
>
>
>
>






<
<
<
<
<
<
<
<
<
<
<







710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736











737
738
739
740
741
742
743
  int rc;
  assert( ppStmt!=0 );
  *ppStmt = 0;
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);
#if SQLITE_USER_AUTHENTICATION
  if( db->auth.authLevel<UAUTH_User ){
    if( db->auth.authLevel==UAUTH_Unknown ){
      u8 authLevel = UAUTH_Fail;
      sqlite3UserAuthCheckLogin(db, "main", &authLevel);
      db->auth.authLevel = authLevel;
    }
    if( db->auth.authLevel<UAUTH_User ){
      sqlite3ErrorWithMsg(db, SQLITE_ERROR, "user not authenticated");
      sqlite3_mutex_leave(db->mutex);
      return SQLITE_ERROR;
    }
  }
#endif
  sqlite3BtreeEnterAll(db);
  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  if( rc==SQLITE_SCHEMA ){
    sqlite3_finalize(*ppStmt);
    rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  }











  sqlite3BtreeLeaveAll(db);
  sqlite3_mutex_leave(db->mutex);
  assert( rc==SQLITE_OK || *ppStmt==0 );
  return rc;
}

/*
Changes to src/sqliteInt.h.
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
#ifdef SQLITE_USER_AUTHENTICATION
/*
** Information held in the "sqlite3" database connection object and used
** to manage user authentication.
*/
typedef struct sqlite3_userauth sqlite3_userauth;
struct sqlite3_userauth {
  u8 authFlags;                 /* Status flags for user authentication */
  int nAuthPW;                  /* Size of the zAuthPW in bytes */
  char *zAuthPW;                /* Password used to authenticate */
  char *zAuthUser;              /* User name used to authenticate */
};

/* Allowed values for sqlite3_userauth.authFlags */
#define UAUTH_Ovrd        0x01  /* Do not enforce access restrictions */
#define UAUTH_Auth        0x02  /* True if the user has authenticated */
#define UAUTH_Admin       0x04  /* True if the user is an administrator */
#define UAUTH_AuthReqd    0x08  /* True if main has an sqlite_user table */

/* Macros for accessing sqlite3.auth.authFlags */
#define DbIsAuth(D)       (((D)->auth.authFlags&UAUTH_Auth)!=0)
#define DbIsAdmin(D)      (((D)->auth.authFlags&UAUTH_Admin)!=0)

/* Functions used only by user authorization logic */
int sqlite3UserAuthTable(const char*);


#endif /* SQLITE_USER_AUTHENTICATION */


/*
** Each database connection is an instance of the following structure.
*/







|





|
|
|
|
<
|
<
<
<



>







991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

1008



1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
#ifdef SQLITE_USER_AUTHENTICATION
/*
** Information held in the "sqlite3" database connection object and used
** to manage user authentication.
*/
typedef struct sqlite3_userauth sqlite3_userauth;
struct sqlite3_userauth {
  u8 authLevel;                 /* Current authentication level */
  int nAuthPW;                  /* Size of the zAuthPW in bytes */
  char *zAuthPW;                /* Password used to authenticate */
  char *zAuthUser;              /* User name used to authenticate */
};

/* Allowed values for sqlite3_userauth.authLevel */
#define UAUTH_Unknown     0     /* Authentication not yet checked */
#define UAUTH_Fail        1     /* User authentication failed */
#define UAUTH_User        2     /* Authenticated as a normal user */

#define UAUTH_Admin       3     /* Authenticated as an administrator */




/* Functions used only by user authorization logic */
int sqlite3UserAuthTable(const char*);
int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);

#endif /* SQLITE_USER_AUTHENTICATION */


/*
** Each database connection is an instance of the following structure.
*/