forked from mirror/go-sqlite3
parent
f7f8019102
commit
4a33fcc1d2
|
@ -1308,7 +1308,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||||
//
|
//
|
||||||
// If the SQLITE_USER table is not present in the database file, then
|
// If the SQLITE_USER table is not present in the database file, then
|
||||||
// this interface is a harmless no-op returnning SQLITE_OK.
|
// this interface is a harmless no-op returnning SQLITE_OK.
|
||||||
if err := conn.RegisterFunc("authenticate", conn.Authenticate, true); err != nil {
|
if err := conn.RegisterFunc("authenticate", conn.Authenticate, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -1321,7 +1321,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||||
// The AuthUserAdd only works for the "main" database, not
|
// The AuthUserAdd only works for the "main" database, not
|
||||||
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
|
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
|
||||||
// non-admin user results in an error.
|
// non-admin user results in an error.
|
||||||
if err := conn.RegisterFunc("auth_user_add", conn.AuthUserAdd, true); err != nil {
|
if err := conn.RegisterFunc("auth_user_add", conn.AuthUserAdd, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -1330,7 +1330,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||||
// login credentials. Only an admin user can change another users login
|
// login credentials. Only an admin user can change another users login
|
||||||
// credentials or admin privilege setting. No user may change their own
|
// credentials or admin privilege setting. No user may change their own
|
||||||
// admin privilege setting.
|
// admin privilege setting.
|
||||||
if err := conn.RegisterFunc("auth_user_change", conn.AuthUserChange, true); err != nil {
|
if err := conn.RegisterFunc("auth_user_change", conn.AuthUserChange, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -1339,7 +1339,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||||
// which guarantees that there is always an admin user and hence that
|
// which guarantees that there is always an admin user and hence that
|
||||||
// the database cannot be converted into a no-authentication-required
|
// the database cannot be converted into a no-authentication-required
|
||||||
// database.
|
// database.
|
||||||
if err := conn.RegisterFunc("auth_user_delete", conn.AuthUserDelete, true); err != nil {
|
if err := conn.RegisterFunc("auth_user_delete", conn.AuthUserDelete, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ _sqlite3_auth_is_enabled(sqlite3* db)
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,6 +68,11 @@ const (
|
||||||
SQLITE_AUTH = C.SQLITE_AUTH
|
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
|
// Authenticate will perform an authentication of the provided username
|
||||||
// and password against the database.
|
// and password against the database.
|
||||||
//
|
//
|
||||||
|
@ -92,6 +98,9 @@ func (c *SQLiteConn) Authenticate(username, password string) error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rv := C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password)))
|
rv := C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password)))
|
||||||
|
if rv == C.SQLITE_AUTH {
|
||||||
|
return ErrUnauthorized
|
||||||
|
}
|
||||||
if rv != C.SQLITE_OK {
|
if rv != C.SQLITE_OK {
|
||||||
return c.lastError()
|
return c.lastError()
|
||||||
}
|
}
|
||||||
|
@ -113,6 +122,18 @@ func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
|
||||||
isAdmin = 1
|
isAdmin = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv := c.authUserAdd(username, password, isAdmin)
|
||||||
|
switch rv {
|
||||||
|
case C.SQLITE_AUTH:
|
||||||
|
return ErrAdminRequired
|
||||||
|
case C.SQLITE_OK:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return c.lastError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SQLiteConn) authUserAdd(username, password string, admin int) int {
|
||||||
// Allocate C Variables
|
// Allocate C Variables
|
||||||
cuser := C.CString(username)
|
cuser := C.CString(username)
|
||||||
cpass := C.CString(password)
|
cpass := C.CString(password)
|
||||||
|
@ -123,12 +144,7 @@ func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
|
||||||
C.free(unsafe.Pointer(cpass))
|
C.free(unsafe.Pointer(cpass))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rv := C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(isAdmin))
|
return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return c.lastError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthUserChange can be used to change a users
|
// AuthUserChange can be used to change a users
|
||||||
|
@ -153,6 +169,9 @@ func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rv := C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(isAdmin))
|
rv := C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(isAdmin))
|
||||||
|
if rv == C.SQLITE_AUTH {
|
||||||
|
return ErrAdminRequired
|
||||||
|
}
|
||||||
if rv != C.SQLITE_OK {
|
if rv != C.SQLITE_OK {
|
||||||
return c.lastError()
|
return c.lastError()
|
||||||
}
|
}
|
||||||
|
@ -175,6 +194,9 @@ func (c *SQLiteConn) AuthUserDelete(username string) error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rv := C._sqlite3_user_delete(c.db, cuser)
|
rv := C._sqlite3_user_delete(c.db, cuser)
|
||||||
|
if rv == SQLITE_AUTH {
|
||||||
|
return ErrAdminRequired
|
||||||
|
}
|
||||||
if rv != C.SQLITE_OK {
|
if rv != C.SQLITE_OK {
|
||||||
return c.lastError()
|
return c.lastError()
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,4 +62,9 @@ func (c *SQLiteConn) AuthUserDelete(username string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check is database is protected by user authentication
|
||||||
|
func (c *SQLiteConn) AuthIsEnabled() (exists bool) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -9,6 +9,7 @@ package sqlite3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -23,11 +24,6 @@ func TestAuthCreateDatabase(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Ping database
|
|
||||||
if err := db.Ping(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
err = db.QueryRow("select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';").Scan(&exists)
|
err = db.QueryRow("select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';").Scan(&exists)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -38,3 +34,51 @@ func TestAuthCreateDatabase(t *testing.T) {
|
||||||
t.Fatal("failed to enable User Authentication")
|
t.Fatal("failed to enable User Authentication")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthorization(t *testing.T) {
|
||||||
|
tempFilename := TempFilename(t)
|
||||||
|
fmt.Println(tempFilename)
|
||||||
|
//defer os.Remove(tempFilename)
|
||||||
|
|
||||||
|
db, err := sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=admin")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Failed to open database:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := db.Exec("select auth_user_add('user', 'user', false);"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var uname string
|
||||||
|
if err := db.QueryRow("select uname from sqlite_user where uname = 'user';").Scan(&uname); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uname != "user" {
|
||||||
|
t.Fatal("Failed to create normal user")
|
||||||
|
}
|
||||||
|
db.Close()
|
||||||
|
|
||||||
|
// Re-Open Database as User
|
||||||
|
// Add User should now fail because we are not admin
|
||||||
|
db, err = sql.Open("sqlite3", "file:"+tempFilename+"?_auth_user=user&_auth_pass=user")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Failed to open database:", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Try to create normal user
|
||||||
|
var rv string
|
||||||
|
if err := db.QueryRow("select auth_user_add('user2', 'user2', false);").Scan(&rv); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("RV: %v\n", rv)
|
||||||
|
// if rv != SQLITE_AUTH {
|
||||||
|
// t.Fatal("Succeeded creating user while not admin")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Try to create admin user
|
||||||
|
// if _, err := db.Exec("select auth_user_add('admin2', 'admin2', true);"); err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue