multiserver/ban.go

153 lines
2.5 KiB
Go

package main
import (
"database/sql"
"errors"
"fmt"
"net"
_ "github.com/mattn/go-sqlite3"
)
var ErrInvalidAddress = errors.New("invalid ip address format")
// addBanItem inserts a ban DB entry
func addBanItem(db *sql.DB, addr, name string) error {
_, err := db.Exec(`INSERT INTO ban (
addr,
name
) VALUES (
?,
?
);`, name)
return err
}
// readBanItem selects and reads a ban DB entry
func readBanItem(db *sql.DB, addr string) (string, error) {
var r string
err := db.QueryRow(`SELECT name FROM ban WHERE addr = ?;`, addr).Scan(&r)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return "", err
}
return r, nil
}
// deleteBanItem deletes a ban DB entry
func deleteBanItem(db *sql.DB, name string) error {
_, err := db.Exec(`DELETE FROM ban WHERE name = ? OR addr = ?;`, name)
return err
}
// BanList returns the list of banned players and IP addresses
func BanList() (map[string]string, error) {
db, err := initAuthDB()
if err != nil {
return nil, err
}
defer db.Close()
rows, err := db.Query(`SELECT addr, name FROM ban;`)
if err != nil {
return nil, err
}
r := make(map[string]string)
for rows.Next() {
var addr, name string
if err = rows.Scan(&addr, &name); err != nil {
return nil, err
}
r[addr] = name
}
return r, nil
}
// IsBanned reports whether a Conn is banned
func (c *Conn) IsBanned() (bool, string, error) {
db, err := initAuthDB()
if err != nil {
return true, "", err
}
defer db.Close()
addr := c.Addr().(*net.UDPAddr).IP.String()
name, err := readBanItem(db, addr)
if err != nil {
return true, "", err
}
return name != "", name, nil
}
// Ban adds a Conn to the ban list
func (c *Conn) Ban() error {
banned, _, err := c.IsBanned()
if err != nil {
return err
}
if banned {
return fmt.Errorf("ip address %s is already banned", c.Addr().String())
}
db, err := initAuthDB()
if err != nil {
return err
}
defer db.Close()
name := c.Username()
addr := c.Addr().(*net.UDPAddr).IP.String()
err = addBanItem(db, addr, name)
if err != nil {
return err
}
c.CloseWith(AccessDeniedCustomString, "Banned.", false)
return nil
}
func Ban(addr string) error {
db, err := initAuthDB()
if err != nil {
return err
}
defer db.Close()
name := "not known"
if net.ParseIP(addr) == nil {
return ErrInvalidAddress
}
err = addBanItem(db, addr, name)
if err != nil {
return err
}
return nil
}
func Unban(name string) error {
db, err := initAuthDB()
if err != nil {
return err
}
defer db.Close()
err = deleteBanItem(db, name)
if err != nil {
return err
}
return nil
}