1 // Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
3 // Use of this source code is governed by an MIT-style
4 // license that can be found in the LICENSE file.
6 // +build sqlite_userauth
11 #cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION
13 #ifndef USE_LIBSQLITE3
14 #include <sqlite3-binding.h>
21 _sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW)
23 return sqlite3_user_authenticate(db, zUsername, aPW, nPW);
27 _sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin)
29 return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin);
33 _sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin)
35 return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin);
39 _sqlite3_user_delete(sqlite3* db, const char* zUsername)
41 return sqlite3_user_delete(db, zUsername);
45 _sqlite3_auth_enabled(sqlite3* db)
50 sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL);
52 while ( sqlite3_step(stmt) == SQLITE_ROW) {
53 exists = sqlite3_column_int(stmt, 0);
56 sqlite3_finalize(stmt);
68 SQLITE_AUTH = C.SQLITE_AUTH
72 ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized")
73 ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required")
76 // Authenticate will perform an authentication of the provided username
77 // and password against the database.
79 // If a database contains the SQLITE_USER table, then the
80 // call to Authenticate must be invoked with an
81 // appropriate username and password prior to enable read and write
82 //access to the database.
84 // Return SQLITE_OK on success or SQLITE_ERROR if the username/password
85 // combination is incorrect or unknown.
87 // If the SQLITE_USER table is not present in the database file, then
88 // this interface is a harmless no-op returnning SQLITE_OK.
89 func (c *SQLiteConn) Authenticate(username, password string) error {
90 rv := c.authenticate(username, password)
92 case C.SQLITE_ERROR, C.SQLITE_AUTH:
93 return ErrUnauthorized
101 // authenticate provides the actual authentication to SQLite.
102 // This is not exported for usage in Go.
103 // It is however exported for usage within SQL by the user.
107 // C.SQLITE_ERROR (1)
108 // C.SQLITE_AUTH (23)
109 func (c *SQLiteConn) authenticate(username, password string) int {
110 // Allocate C Variables
111 cuser := C.CString(username)
112 cpass := C.CString(password)
116 C.free(unsafe.Pointer(cuser))
117 C.free(unsafe.Pointer(cpass))
120 return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password))))
123 // AuthUserAdd can be used (by an admin user only)
124 // to create a new user. When called on a no-authentication-required
125 // database, this routine converts the database into an authentication-
126 // required database, automatically makes the added user an
127 // administrator, and logs in the current connection as that user.
128 // The AuthUserAdd only works for the "main" database, not
129 // for any ATTACH-ed databases. Any call to AuthUserAdd by a
130 // non-admin user results in an error.
131 func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
137 rv := c.authUserAdd(username, password, isAdmin)
139 case C.SQLITE_ERROR, C.SQLITE_AUTH:
140 return ErrAdminRequired
148 // authUserAdd enables the User Authentication if not enabled.
149 // Otherwise it will add a user.
151 // When user authentication is already enabled then this function
152 // can only be called by an admin.
154 // This is not exported for usage in Go.
155 // It is however exported for usage within SQL by the user.
159 // C.SQLITE_ERROR (1)
160 // C.SQLITE_AUTH (23)
161 func (c *SQLiteConn) authUserAdd(username, password string, admin int) int {
162 // Allocate C Variables
163 cuser := C.CString(username)
164 cpass := C.CString(password)
168 C.free(unsafe.Pointer(cuser))
169 C.free(unsafe.Pointer(cpass))
172 return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
175 // AuthUserChange can be used to change a users
176 // login credentials or admin privilege. Any user can change their own
177 // login credentials. Only an admin user can change another users login
178 // credentials or admin privilege setting. No user may change their own
179 // admin privilege setting.
180 func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error {
186 rv := c.authUserChange(username, password, isAdmin)
188 case C.SQLITE_ERROR, C.SQLITE_AUTH:
189 return ErrAdminRequired
197 // authUserChange allows to modify a user.
198 // Users can change their own password.
200 // Only admins can change passwords for other users
201 // and modify the admin flag.
203 // The admin flag of the current logged in user cannot be changed.
204 // THis ensures that their is always an admin.
206 // This is not exported for usage in Go.
207 // It is however exported for usage within SQL by the user.
211 // C.SQLITE_ERROR (1)
212 // C.SQLITE_AUTH (23)
213 func (c *SQLiteConn) authUserChange(username, password string, admin int) int {
214 // Allocate C Variables
215 cuser := C.CString(username)
216 cpass := C.CString(password)
220 C.free(unsafe.Pointer(cuser))
221 C.free(unsafe.Pointer(cpass))
224 return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
227 // AuthUserDelete can be used (by an admin user only)
228 // to delete a user. The currently logged-in user cannot be deleted,
229 // which guarantees that there is always an admin user and hence that
230 // the database cannot be converted into a no-authentication-required
232 func (c *SQLiteConn) AuthUserDelete(username string) error {
233 rv := c.authUserDelete(username)
235 case C.SQLITE_ERROR, C.SQLITE_AUTH:
236 return ErrAdminRequired
244 // authUserDelete can be used to delete a user.
246 // This function can only be executed by an admin.
248 // This is not exported for usage in Go.
249 // It is however exported for usage within SQL by the user.
253 // C.SQLITE_ERROR (1)
254 // C.SQLITE_AUTH (23)
255 func (c *SQLiteConn) authUserDelete(username string) int {
256 // Allocate C Variables
257 cuser := C.CString(username)
261 C.free(unsafe.Pointer(cuser))
264 return int(C._sqlite3_user_delete(c.db, cuser))
267 // AuthEnabled checks if the database is protected by user authentication
268 func (c *SQLiteConn) AuthEnabled() (exists bool) {
269 rv := c.authEnabled()
277 // authEnabled perform the actual check for user authentication.
279 // This is not exported for usage in Go.
280 // It is however exported for usage within SQL by the user.
285 func (c *SQLiteConn) authEnabled() int {
286 return int(C._sqlite3_auth_enabled(c.db))