Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enhance the sqlite3_user_add() interface to initialize the user authentication logic. Add test cases for the extra argument on the end of the authorizer callback. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | user-auth |
Files: | files | file ages | folders |
SHA1: |
842c6da8f1a62bd13a1b4089a98b0835 |
User & Date: | drh 2014-09-11 16:19:31.719 |
Context
2014-09-11
| ||
16:36 | Suppress the potential schema error that occurs when a non-user-auth SQLite library tries to parse the sqlite_user table definition in a user-auth database. (check-in: cda33c1ef3 user: drh tags: user-auth) | |
16:19 | Enhance the sqlite3_user_add() interface to initialize the user authentication logic. Add test cases for the extra argument on the end of the authorizer callback. (check-in: 842c6da8f1 user: drh tags: user-auth) | |
15:25 | All interfaces working and tested. (check-in: 96ea5c0b3c user: drh tags: user-auth) | |
Changes
Changes to ext/userauth/userauth.c.
︙ | ︙ | |||
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 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; } /* ** Implementation of the sqlite_crypt(X,Y) function. ** ** If Y is NULL then generate a new hash for password X and return that ** hash. If Y is not null, then generate a hash for password X using the ** same salt as the previous hash Y and return the new hash. | > > > > > > > > > > > > > > > | 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 | 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; assert( zDb!=0 ); assert( peAuth!=0 ); savedAuthLevel = db->auth.authLevel; db->auth.authLevel = UAUTH_Admin; rc = userAuthCheckLogin(db, zDb, peAuth); db->auth.authLevel = savedAuthLevel; return rc; } /* ** If the current authLevel is UAUTH_Unknown, the take actions to figure ** out what authLevel should be */ void sqlite3UserAuthInit(sqlite3 *db){ if( db->auth.authLevel==UAUTH_Unknown ){ u8 authLevel = UAUTH_Fail; sqlite3UserAuthCheckLogin(db, "main", &authLevel); db->auth.authLevel = authLevel; if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema; } } /* ** Implementation of the sqlite_crypt(X,Y) function. ** ** If Y is NULL then generate a new hash for password X and return that ** hash. If Y is not null, then generate a hash for password X using the ** same salt as the previous hash Y and return the new hash. |
︙ | ︙ | |||
219 220 221 222 223 224 225 226 227 228 229 230 231 232 | const char *zUsername, /* Username to be added */ const char *aPW, /* Password or credentials */ int nPW, /* Number of bytes in aPW[] */ int isAdmin /* True to give new user admin privilege */ ){ sqlite3_stmt *pStmt; int rc; if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH; if( !userTableExists(db, "main") ){ if( !isAdmin ) return SQLITE_AUTH; pStmt = sqlite3UserAuthPrepare(db, "CREATE TABLE sqlite_user(\n" " uname TEXT PRIMARY KEY,\n" " isAdmin BOOLEAN,\n" | > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | const char *zUsername, /* Username to be added */ const char *aPW, /* Password or credentials */ int nPW, /* Number of bytes in aPW[] */ int isAdmin /* True to give new user admin privilege */ ){ sqlite3_stmt *pStmt; int rc; sqlite3UserAuthInit(db); if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH; if( !userTableExists(db, "main") ){ if( !isAdmin ) return SQLITE_AUTH; pStmt = sqlite3UserAuthPrepare(db, "CREATE TABLE sqlite_user(\n" " uname TEXT PRIMARY KEY,\n" " isAdmin BOOLEAN,\n" |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
154 155 156 157 158 159 160 | || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} sqlite3VdbeAddOp0(v, OP_Halt); #if SQLITE_USER_AUTHENTICATION if( pParse->nTableLock>0 && db->init.busy==0 ){ | < < < | < < < | | | | < | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} sqlite3VdbeAddOp0(v, OP_Halt); #if SQLITE_USER_AUTHENTICATION if( pParse->nTableLock>0 && db->init.busy==0 ){ sqlite3UserAuthInit(db); if( db->auth.authLevel<UAUTH_User ){ pParse->rc = SQLITE_AUTH_USER; sqlite3ErrorMsg(pParse, "user not authenticated"); return; } } #endif /* The cookie mask contains one bit for each database file open. ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are ** set for each database that is used. Generate code to start a |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 | #if SQLITE_USER_AUTHENTICATION if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ if( nArg<2 ){ fprintf(stderr, "Usage: .user SUBCOMMAND ...\n"); rc = 1; goto meta_command_exit; } if( strcmp(azArg[1],"login")==0 ){ if( nArg!=4 ){ fprintf(stderr, "Usage: .user login USER PASSWORD\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], | > | 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 | #if SQLITE_USER_AUTHENTICATION if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ if( nArg<2 ){ fprintf(stderr, "Usage: .user SUBCOMMAND ...\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); if( strcmp(azArg[1],"login")==0 ){ if( nArg!=4 ){ fprintf(stderr, "Usage: .user login USER PASSWORD\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | #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*); void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); #endif /* SQLITE_USER_AUTHENTICATION */ /* ** typedef for the authorization callback function. */ | > | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | #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*); void sqlite3UserAuthInit(sqlite3*); void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); #endif /* SQLITE_USER_AUTHENTICATION */ /* ** typedef for the authorization callback function. */ |
︙ | ︙ |
Changes to test/userauth01.test.
︙ | ︙ | |||
205 206 207 208 209 210 211 212 213 214 215 216 | # database that is an authentication-required database is checked using # the same username and password as supplied to the main database. If that # check fails, then the ATTACH command fails with an SQLITE_AUTH error. # do_test userauth01-1.60 { forcedelete test3.db sqlite3 db3 test3.db db3 eval { CREATE TABLE t3(a,b,c); INSERT INTO t3 VALUES(1,2,3); SELECT * FROM t3; } } {1 2 3} | > > > < < < > > > > > > > > > > > > > > > > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | # database that is an authentication-required database is checked using # the same username and password as supplied to the main database. If that # check fails, then the ATTACH command fails with an SQLITE_AUTH error. # do_test userauth01-1.60 { forcedelete test3.db sqlite3 db3 test3.db sqlite3_user_add db3 alice xyzzy-alice 1 } {SQLITE_OK} do_test userauth01-1.61 { db3 eval { CREATE TABLE t3(a,b,c); INSERT INTO t3 VALUES(1,2,3); SELECT * FROM t3; } } {1 2 3} do_test userauth01-1.62 { db eval { ATTACH 'test3.db' AS aux; SELECT * FROM t1, t3 ORDER BY x LIMIT 1; DETACH aux; } } {{} 1 2 3} do_test userauth01-1.63 { sqlite3_user_change db alice pw-4-alice 1 sqlite3_user_authenticate db alice pw-4-alice catchsql { ATTACH 'test3.db' AS aux; } } {1 {unable to open database: test3.db}} do_test userauth01-1.64 { sqlite3_extended_errcode db } {SQLITE_AUTH} do_test userauth01-1.65 { db eval {PRAGMA database_list} } {~/test3.db/} # The sqlite3_set_authorizer() callback is modified to take a 7th parameter # which is the username of the currently logged in user, or NULL for a # no-authentication-required database. # proc auth {args} { lappend ::authargs $args return SQLITE_OK } do_test authuser01-2.1 { unset -nocomplain ::authargs db auth auth db eval {SELECT x FROM t1} set ::authargs } {/SQLITE_SELECT {} {} {} {} alice/} finish_test |