@ -0,0 +1,120 @@ | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
package sqlite3 | |||
import ( | |||
"crypto/sha1" | |||
"crypto/sha256" | |||
"crypto/sha512" | |||
) | |||
// This file provides several different implementations for the | |||
// default embedded sqlite_crypt function. | |||
// This function is uses a ceasar-cypher by default | |||
// and is used within the UserAuthentication module to encode | |||
// the password. | |||
// | |||
// The provided functions can be used as an overload to the sqlite_crypt | |||
// function through the use of the RegisterFunc on the connection. | |||
// | |||
// Because the functions can serv a purpose to an end-user | |||
// without using the UserAuthentication module | |||
// the functions are default compiled in. | |||
// | |||
// From SQLITE3 - user-auth.txt | |||
// The sqlite_user.pw field is encoded by a built-in SQL function | |||
// "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument | |||
// is the plaintext password supplied to the sqlite3_user_authenticate() | |||
// interface. The second argument is the sqlite_user.pw value and is supplied | |||
// so that the function can extract the "salt" used by the password encoder. | |||
// The result of sqlite_crypt(X,Y) is another blob which is the value that | |||
// ends up being stored in sqlite_user.pw. To verify credentials X supplied | |||
// by the sqlite3_user_authenticate() routine, SQLite runs: | |||
// | |||
// sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw) | |||
// | |||
// To compute an appropriate sqlite_user.pw value from a new or modified | |||
// password X, sqlite_crypt(X,NULL) is run. A new random salt is selected | |||
// when the second argument is NULL. | |||
// | |||
// The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher | |||
// which prevents passwords from being revealed by searching the raw database | |||
// for ASCII text, but is otherwise trivally broken. For better password | |||
// security, the database should be encrypted using the SQLite Encryption | |||
// Extension or similar technology. Or, the application can use the | |||
// sqlite3_create_function() interface to provide an alternative | |||
// implementation of sqlite_crypt() that computes a stronger password hash, | |||
// perhaps using a cryptographic hash function like SHA1. | |||
// CryptEncoderSHA1 encodes a password with SHA1 | |||
func CryptEncoderSHA1(pass []byte, hash interface{}) []byte { | |||
h := sha1.Sum(pass) | |||
return h[:] | |||
} | |||
// CryptEncoderSSHA1 encodes a password with SHA1 with the | |||
// configured salt. | |||
func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte { | |||
return func(pass []byte, hash interface{}) []byte { | |||
s := []byte(salt) | |||
p := append(pass, s...) | |||
h := sha1.Sum(p) | |||
return h[:] | |||
} | |||
} | |||
// CryptEncoderSHA256 encodes a password with SHA256 | |||
func CryptEncoderSHA256(pass []byte, hash interface{}) []byte { | |||
h := sha256.Sum256(pass) | |||
return h[:] | |||
} | |||
// CryptEncoderSSHA256 encodes a password with SHA256 | |||
// with the configured salt | |||
func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte { | |||
return func(pass []byte, hash interface{}) []byte { | |||
s := []byte(salt) | |||
p := append(pass, s...) | |||
h := sha256.Sum256(p) | |||
return h[:] | |||
} | |||
} | |||
// CryptEncoderSHA384 encodes a password with SHA384 | |||
func CryptEncoderSHA384(pass []byte, hash interface{}) []byte { | |||
h := sha512.Sum384(pass) | |||
return h[:] | |||
} | |||
// CryptEncoderSSHA384 encodes a password with SHA384 | |||
// with the configured salt | |||
func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte { | |||
return func(pass []byte, hash interface{}) []byte { | |||
s := []byte(salt) | |||
p := append(pass, s...) | |||
h := sha512.Sum384(p) | |||
return h[:] | |||
} | |||
} | |||
// CryptEncoderSHA512 encodes a password with SHA512 | |||
func CryptEncoderSHA512(pass []byte, hash interface{}) []byte { | |||
h := sha512.Sum512(pass) | |||
return h[:] | |||
} | |||
// CryptEncoderSSHA512 encodes a password with SHA512 | |||
// with the configured salt | |||
func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte { | |||
return func(pass []byte, hash interface{}) []byte { | |||
s := []byte(salt) | |||
p := append(pass, s...) | |||
h := sha512.Sum512(p) | |||
return h[:] | |||
} | |||
} | |||
// EOF |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_allow_uri_authority | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,16 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build !windows | |||
// +build sqlite_app_armor | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_foreign_keys | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1 | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_introspect | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_secure_delete | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_SECURE_DELETE=1 | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_secure_delete_fast | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_stat4 | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_ENABLE_STAT4 | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,85 @@ | |||
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY | |||
#include <stdio.h> | |||
#include <sqlite3-binding.h> | |||
extern int unlock_notify_wait(sqlite3 *db); | |||
int | |||
_sqlite3_step_blocking(sqlite3_stmt *stmt) | |||
{ | |||
int rv; | |||
sqlite3* db; | |||
db = sqlite3_db_handle(stmt); | |||
for (;;) { | |||
rv = sqlite3_step(stmt); | |||
if (rv != SQLITE_LOCKED) { | |||
break; | |||
} | |||
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { | |||
break; | |||
} | |||
rv = unlock_notify_wait(db); | |||
if (rv != SQLITE_OK) { | |||
break; | |||
} | |||
sqlite3_reset(stmt); | |||
} | |||
return rv; | |||
} | |||
int | |||
_sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes) | |||
{ | |||
int rv; | |||
sqlite3* db; | |||
db = sqlite3_db_handle(stmt); | |||
for (;;) { | |||
rv = sqlite3_step(stmt); | |||
if (rv!=SQLITE_LOCKED) { | |||
break; | |||
} | |||
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { | |||
break; | |||
} | |||
rv = unlock_notify_wait(db); | |||
if (rv != SQLITE_OK) { | |||
break; | |||
} | |||
sqlite3_reset(stmt); | |||
} | |||
*rowid = (long long) sqlite3_last_insert_rowid(db); | |||
*changes = (long long) sqlite3_changes(db); | |||
return rv; | |||
} | |||
int | |||
_sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail) | |||
{ | |||
int rv; | |||
for (;;) { | |||
rv = sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail); | |||
if (rv!=SQLITE_LOCKED) { | |||
break; | |||
} | |||
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { | |||
break; | |||
} | |||
rv = unlock_notify_wait(db); | |||
if (rv != SQLITE_OK) { | |||
break; | |||
} | |||
} | |||
return rv; | |||
} | |||
#endif |
@ -0,0 +1,92 @@ | |||
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build cgo | |||
// +build sqlite_unlock_notify | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY | |||
#include <stdlib.h> | |||
#include <sqlite3-binding.h> | |||
extern void unlock_notify_callback(void *arg, int argc); | |||
*/ | |||
import "C" | |||
import ( | |||
"fmt" | |||
"sync" | |||
"unsafe" | |||
) | |||
type unlock_notify_table struct { | |||
sync.Mutex | |||
seqnum uint | |||
table map[uint]chan struct{} | |||
} | |||
var unt unlock_notify_table = unlock_notify_table{table: make(map[uint]chan struct{})} | |||
func (t *unlock_notify_table) add(c chan struct{}) uint { | |||
t.Lock() | |||
defer t.Unlock() | |||
h := t.seqnum | |||
t.table[h] = c | |||
t.seqnum++ | |||
return h | |||
} | |||
func (t *unlock_notify_table) remove(h uint) { | |||
t.Lock() | |||
defer t.Unlock() | |||
delete(t.table, h) | |||
} | |||
func (t *unlock_notify_table) get(h uint) chan struct{} { | |||
t.Lock() | |||
defer t.Unlock() | |||
c, ok := t.table[h] | |||
if !ok { | |||
panic(fmt.Sprintf("Non-existent key for unlcok-notify channel: %d", h)) | |||
} | |||
return c | |||
} | |||
//export unlock_notify_callback | |||
func unlock_notify_callback(argv unsafe.Pointer, argc C.int) { | |||
for i := 0; i < int(argc); i++ { | |||
parg := ((*(*[1 << 30]*[1]uint)(argv))[i]) | |||
arg := *parg | |||
h := arg[0] | |||
c := unt.get(h) | |||
c <- struct{}{} | |||
} | |||
} | |||
//export unlock_notify_wait | |||
func unlock_notify_wait(db *C.sqlite3) C.int { | |||
// It has to be a bufferred channel to not block in sqlite_unlock_notify | |||
// as sqlite_unlock_notify could invoke the callback before it returns. | |||
c := make(chan struct{}, 1) | |||
defer close(c) | |||
h := unt.add(c) | |||
defer unt.remove(h) | |||
pargv := C.malloc(C.sizeof_uint) | |||
defer C.free(pargv) | |||
argv := (*[1]uint)(pargv) | |||
argv[0] = h | |||
if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C.unlock_notify_callback), unsafe.Pointer(pargv)); rv != C.SQLITE_OK { | |||
return rv | |||
} | |||
<-c | |||
return C.SQLITE_OK | |||
} |
@ -0,0 +1,289 @@ | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_userauth | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION | |||
#cgo LDFLAGS: -lm | |||
#ifndef USE_LIBSQLITE3 | |||
#include <sqlite3-binding.h> | |||
#else | |||
#include <sqlite3.h> | |||
#endif | |||
#include <stdlib.h> | |||
static int | |||
_sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW) | |||
{ | |||
return sqlite3_user_authenticate(db, zUsername, aPW, nPW); | |||
} | |||
static int | |||
_sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) | |||
{ | |||
return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin); | |||
} | |||
static int | |||
_sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) | |||
{ | |||
return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin); | |||
} | |||
static int | |||
_sqlite3_user_delete(sqlite3* db, const char* zUsername) | |||
{ | |||
return sqlite3_user_delete(db, zUsername); | |||
} | |||
static int | |||
_sqlite3_auth_enabled(sqlite3* db) | |||
{ | |||
int exists = -1; | |||
sqlite3_stmt *stmt; | |||
sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL); | |||
while ( sqlite3_step(stmt) == SQLITE_ROW) { | |||
exists = sqlite3_column_int(stmt, 0); | |||
} | |||
sqlite3_finalize(stmt); | |||
return exists; | |||
} | |||
*/ | |||
import "C" | |||
import ( | |||
"errors" | |||
"unsafe" | |||
) | |||
const ( | |||
SQLITE_AUTH = C.SQLITE_AUTH | |||
) | |||
var ( | |||
ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized") | |||
ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required") | |||
) | |||
// Authenticate will perform an authentication of the provided username | |||
// and password against the database. | |||
// | |||
// If a database contains the SQLITE_USER table, then the | |||
// call to Authenticate 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. | |||
func (c *SQLiteConn) Authenticate(username, password string) error { | |||
rv := c.authenticate(username, password) | |||
switch rv { | |||
case C.SQLITE_ERROR, C.SQLITE_AUTH: | |||
return ErrUnauthorized | |||
case C.SQLITE_OK: | |||
return nil | |||
default: | |||
return c.lastError() | |||
} | |||
} | |||
// authenticate provides the actual authentication to SQLite. | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authenticate(username, password string) int { | |||
// Allocate C Variables | |||
cuser := C.CString(username) | |||
cpass := C.CString(password) | |||
// Free C Variables | |||
defer func() { | |||
C.free(unsafe.Pointer(cuser)) | |||
C.free(unsafe.Pointer(cpass)) | |||
}() | |||
return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password)))) | |||
} | |||
// AuthUserAdd 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 AuthUserAdd only works for the "main" database, not | |||
// for any ATTACH-ed databases. Any call to AuthUserAdd by a | |||
// non-admin user results in an error. | |||
func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { | |||
isAdmin := 0 | |||
if admin { | |||
isAdmin = 1 | |||
} | |||
rv := c.authUserAdd(username, password, isAdmin) | |||
switch rv { | |||
case C.SQLITE_ERROR, C.SQLITE_AUTH: | |||
return ErrAdminRequired | |||
case C.SQLITE_OK: | |||
return nil | |||
default: | |||
return c.lastError() | |||
} | |||
} | |||
// authUserAdd enables the User Authentication if not enabled. | |||
// Otherwise it will add a user. | |||
// | |||
// When user authentication is already enabled then this function | |||
// can only be called by an admin. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { | |||
// Allocate C Variables | |||
cuser := C.CString(username) | |||
cpass := C.CString(password) | |||
// Free C Variables | |||
defer func() { | |||
C.free(unsafe.Pointer(cuser)) | |||
C.free(unsafe.Pointer(cpass)) | |||
}() | |||
return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) | |||
} | |||
// AuthUserChange 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. | |||
func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { | |||
isAdmin := 0 | |||
if admin { | |||
isAdmin = 1 | |||
} | |||
rv := c.authUserChange(username, password, isAdmin) | |||
switch rv { | |||
case C.SQLITE_ERROR, C.SQLITE_AUTH: | |||
return ErrAdminRequired | |||
case C.SQLITE_OK: | |||
return nil | |||
default: | |||
return c.lastError() | |||
} | |||
} | |||
// authUserChange allows to modify a user. | |||
// Users can change their own password. | |||
// | |||
// Only admins can change passwords for other users | |||
// and modify the admin flag. | |||
// | |||
// The admin flag of the current logged in user cannot be changed. | |||
// THis ensures that their is always an admin. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authUserChange(username, password string, admin int) int { | |||
// Allocate C Variables | |||
cuser := C.CString(username) | |||
cpass := C.CString(password) | |||
// Free C Variables | |||
defer func() { | |||
C.free(unsafe.Pointer(cuser)) | |||
C.free(unsafe.Pointer(cpass)) | |||
}() | |||
return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) | |||
} | |||
// AuthUserDelete 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. | |||
func (c *SQLiteConn) AuthUserDelete(username string) error { | |||
rv := c.authUserDelete(username) | |||
switch rv { | |||
case C.SQLITE_ERROR, C.SQLITE_AUTH: | |||
return ErrAdminRequired | |||
case C.SQLITE_OK: | |||
return nil | |||
default: | |||
return c.lastError() | |||
} | |||
} | |||
// authUserDelete can be used to delete a user. | |||
// | |||
// This function can only be executed by an admin. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authUserDelete(username string) int { | |||
// Allocate C Variables | |||
cuser := C.CString(username) | |||
// Free C Variables | |||
defer func() { | |||
C.free(unsafe.Pointer(cuser)) | |||
}() | |||
return int(C._sqlite3_user_delete(c.db, cuser)) | |||
} | |||
// AuthEnabled checks if the database is protected by user authentication | |||
func (c *SQLiteConn) AuthEnabled() (exists bool) { | |||
rv := c.authEnabled() | |||
if rv == 1 { | |||
exists = true | |||
} | |||
return | |||
} | |||
// authEnabled perform the actual check for user authentication. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// 0 - Disabled | |||
// 1 - Enabled | |||
func (c *SQLiteConn) authEnabled() int { | |||
return int(C._sqlite3_auth_enabled(c.db)) | |||
} | |||
// EOF |
@ -0,0 +1,152 @@ | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build !sqlite_userauth | |||
package sqlite3 | |||
import ( | |||
"C" | |||
) | |||
// Authenticate will perform an authentication of the provided username | |||
// and password against the database. | |||
// | |||
// If a database contains the SQLITE_USER table, then the | |||
// call to Authenticate 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. | |||
func (c *SQLiteConn) Authenticate(username, password string) error { | |||
// NOOP | |||
return nil | |||
} | |||
// authenticate provides the actual authentication to SQLite. | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authenticate(username, password string) int { | |||
// NOOP | |||
return 0 | |||
} | |||
// AuthUserAdd 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 AuthUserAdd only works for the "main" database, not | |||
// for any ATTACH-ed databases. Any call to AuthUserAdd by a | |||
// non-admin user results in an error. | |||
func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { | |||
// NOOP | |||
return nil | |||
} | |||
// authUserAdd enables the User Authentication if not enabled. | |||
// Otherwise it will add a user. | |||
// | |||
// When user authentication is already enabled then this function | |||
// can only be called by an admin. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { | |||
// NOOP | |||
return 0 | |||
} | |||
// AuthUserChange 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. | |||
func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { | |||
// NOOP | |||
return nil | |||
} | |||
// authUserChange allows to modify a user. | |||
// Users can change their own password. | |||
// | |||
// Only admins can change passwords for other users | |||
// and modify the admin flag. | |||
// | |||
// The admin flag of the current logged in user cannot be changed. | |||
// THis ensures that their is always an admin. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authUserChange(username, password string, admin int) int { | |||
// NOOP | |||
return 0 | |||
} | |||
// AuthUserDelete 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. | |||
func (c *SQLiteConn) AuthUserDelete(username string) error { | |||
// NOOP | |||
return nil | |||
} | |||
// authUserDelete can be used to delete a user. | |||
// | |||
// This function can only be executed by an admin. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// C.SQLITE_OK (0) | |||
// C.SQLITE_ERROR (1) | |||
// C.SQLITE_AUTH (23) | |||
func (c *SQLiteConn) authUserDelete(username string) int { | |||
// NOOP | |||
return 0 | |||
} | |||
// AuthEnabled checks if the database is protected by user authentication | |||
func (c *SQLiteConn) AuthEnabled() (exists bool) { | |||
// NOOP | |||
return false | |||
} | |||
// authEnabled perform the actual check for user authentication. | |||
// | |||
// This is not exported for usage in Go. | |||
// It is however exported for usage within SQL by the user. | |||
// | |||
// Returns: | |||
// 0 - Disabled | |||
// 1 - Enabled | |||
func (c *SQLiteConn) authEnabled() int { | |||
// NOOP | |||
return 0 | |||
} | |||
// EOF |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_vacuum_full | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1 | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,15 @@ | |||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build sqlite_vacuum_incr | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2 | |||
#cgo LDFLAGS: -lm | |||
*/ | |||
import "C" |
@ -0,0 +1,14 @@ | |||
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build solaris | |||
package sqlite3 | |||
/* | |||
#cgo CFLAGS: -D__EXTENSIONS__=1 | |||
#cgo LDFLAGS: -lc | |||
*/ | |||
import "C" |
@ -0,0 +1,39 @@ | |||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>. | |||
// | |||
// Use of this source code is governed by an MIT-style | |||
// license that can be found in the LICENSE file. | |||
// +build cgo | |||
package sqlite3 | |||
// usleep is a function available on *nix based systems. | |||
// This function is not present in Windows. | |||
// Windows has a sleep function but this works with seconds | |||
// and not with microseconds as usleep. | |||
// | |||
// This code should improve performance on windows because | |||
// without the presence of usleep SQLite waits 1 second. | |||
// | |||
// Source: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa | |||
/* | |||
#include <windows.h> | |||
void usleep(__int64 usec) | |||
{ | |||
HANDLE timer; | |||
LARGE_INTEGER ft; | |||
// Convert to 100 nanosecond interval, negative value indicates relative time | |||
ft.QuadPart = -(10*usec); | |||
timer = CreateWaitableTimer(NULL, TRUE, NULL); | |||
SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); | |||
WaitForSingleObject(timer, INFINITE); | |||
CloseHandle(timer); | |||
} | |||
*/ | |||
import "C" | |||
// EOF |
@ -0,0 +1,21 @@ | |||
// +build !cgo | |||
package sqlite3 | |||
import ( | |||
"database/sql" | |||
"database/sql/driver" | |||
"errors" | |||
) | |||
func init() { | |||
sql.Register("sqlite3", &SQLiteDriverMock{}) | |||
} | |||
type SQLiteDriverMock struct{} | |||
var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub") | |||
func (SQLiteDriverMock) Open(s string) (driver.Conn, error) { | |||
return nil, errorMsg | |||
} |