2021-01-24 05:00:26 -08:00
|
|
|
package main
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
import (
|
2021-01-16 13:23:52 -08:00
|
|
|
"crypto/rand"
|
2021-01-09 13:01:36 -08:00
|
|
|
"database/sql"
|
|
|
|
"encoding/base64"
|
2021-04-01 13:06:26 -07:00
|
|
|
"errors"
|
2021-01-16 13:23:52 -08:00
|
|
|
"log"
|
2021-01-09 13:01:36 -08:00
|
|
|
"os"
|
|
|
|
"strings"
|
2021-01-18 13:08:22 -08:00
|
|
|
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
2021-01-09 13:01:36 -08:00
|
|
|
)
|
|
|
|
|
2021-01-11 12:45:46 -08:00
|
|
|
const (
|
2021-04-01 01:28:28 -07:00
|
|
|
_ = 1 << iota
|
|
|
|
AuthMechSRP
|
|
|
|
AuthMechFirstSRP
|
2021-01-11 12:45:46 -08:00
|
|
|
)
|
|
|
|
|
2021-01-16 13:23:52 -08:00
|
|
|
var passPhrase []byte
|
2021-01-14 11:18:58 -08:00
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
// encodeVerifierAndSalt encodes SRP verifier and salt into DB-ready string
|
|
|
|
func encodeVerifierAndSalt(s, v []byte) string {
|
|
|
|
return base64.StdEncoding.EncodeToString(s) + "#" + base64.StdEncoding.EncodeToString(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
// decodeVerifierAndSalt decodes DB-ready string into SRP verifier and salt
|
|
|
|
func decodeVerifierAndSalt(src string) ([]byte, []byte, error) {
|
|
|
|
sString := strings.Split(src, "#")[0]
|
|
|
|
vString := strings.Split(src, "#")[1]
|
|
|
|
|
|
|
|
s, err := base64.StdEncoding.DecodeString(sString)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := base64.StdEncoding.DecodeString(vString)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return s, v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// initAuthDB opens auth.sqlite and creates the required tables
|
|
|
|
// if they don't exist
|
|
|
|
// It returns said database
|
|
|
|
func initAuthDB() (*sql.DB, error) {
|
2021-03-09 08:07:10 -08:00
|
|
|
os.Mkdir("storage", 0777)
|
2021-01-10 13:45:45 -08:00
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
db, err := sql.Open("sqlite3", "storage/auth.sqlite")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-04-01 01:28:28 -07:00
|
|
|
if _, err := db.Exec(`
|
|
|
|
CREATE TABLE IF NOT EXISTS auth (
|
|
|
|
name VARCHAR(32) NOT NULL,
|
|
|
|
password VARCHAR(512) NOT NULL
|
|
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS privileges (
|
|
|
|
name VARCHAR(32) NOT NULL,
|
|
|
|
privileges VARCHAR(1024)
|
|
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS ban (
|
|
|
|
addr VARCHAR(39) NOT NULL,
|
|
|
|
name VARCHAR(32) NOT NULL
|
|
|
|
);
|
|
|
|
`); err != nil {
|
|
|
|
db.Close()
|
2021-01-09 13:01:36 -08:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return db, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// addAuthItem inserts an auth DB entry
|
|
|
|
func addAuthItem(db *sql.DB, name, password string) error {
|
2021-04-01 01:28:28 -07:00
|
|
|
_, err := db.Exec(`INSERT INTO auth (
|
2021-01-09 13:01:36 -08:00
|
|
|
name,
|
|
|
|
password
|
|
|
|
) VALUES (
|
|
|
|
?,
|
|
|
|
?
|
2021-04-01 01:28:28 -07:00
|
|
|
);`, name, password)
|
|
|
|
return err
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// modAuthItem updates an auth DB entry
|
|
|
|
func modAuthItem(db *sql.DB, name, password string) error {
|
2021-04-01 01:28:28 -07:00
|
|
|
_, err := db.Exec(`UPDATE auth SET password = ? WHERE name = ?;`, password, name)
|
|
|
|
return err
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// readAuthItem selects and reads an auth DB entry
|
|
|
|
func readAuthItem(db *sql.DB, name string) (string, error) {
|
|
|
|
var r string
|
2021-04-01 01:28:28 -07:00
|
|
|
err := db.QueryRow(`SELECT password FROM auth WHERE name = ?;`, name).Scan(&r)
|
2021-04-01 13:06:26 -07:00
|
|
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return r, nil
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
2021-01-16 13:23:52 -08:00
|
|
|
|
|
|
|
func init() {
|
2021-03-09 13:23:41 -08:00
|
|
|
pwd, err := StorageKey("auth:passphrase")
|
2021-01-16 13:23:52 -08:00
|
|
|
if err != nil {
|
2021-03-02 07:57:19 -08:00
|
|
|
log.Fatal(err)
|
2021-01-16 13:23:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if pwd == "" {
|
|
|
|
passPhrase = make([]byte, 16)
|
|
|
|
_, err := rand.Read(passPhrase)
|
|
|
|
if err != nil {
|
2021-03-02 07:57:19 -08:00
|
|
|
log.Fatal(err)
|
2021-01-16 13:23:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save the passphrase for future use
|
|
|
|
// This passphrase should not be changed unless you delete
|
|
|
|
// the auth databases on the minetest servers
|
2021-01-17 12:43:23 -08:00
|
|
|
err = SetStorageKey("auth:passphrase", string(passPhrase))
|
2021-01-16 13:23:52 -08:00
|
|
|
if err != nil {
|
2021-03-02 07:57:19 -08:00
|
|
|
log.Fatal(err)
|
2021-01-16 13:23:52 -08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
passPhrase = []byte(pwd)
|
|
|
|
}
|
|
|
|
}
|