aboutsummaryrefslogtreecommitdiff
path: root/auth_files.go
diff options
context:
space:
mode:
Diffstat (limited to 'auth_files.go')
-rw-r--r--auth_files.go193
1 files changed, 193 insertions, 0 deletions
diff --git a/auth_files.go b/auth_files.go
new file mode 100644
index 0000000..22b1e60
--- /dev/null
+++ b/auth_files.go
@@ -0,0 +1,193 @@
+package proxy
+
+import (
+ "net"
+ "os"
+ "time"
+)
+
+type authFiles struct{}
+
+// Exists reports whether a user is registered.
+func (a authFiles) Exists(name string) bool {
+ os.Mkdir(Path("auth"), 0700)
+
+ _, err := os.Stat(Path("auth/", name))
+ return err == nil
+}
+
+// Passwd returns the SRP salt and verifier of a user or an error.
+func (a authFiles) Passwd(name string) (salt, verifier []byte, err error) {
+ os.Mkdir(Path("auth"), 0700)
+
+ salt, err = os.ReadFile(Path("auth/", name, "/salt"))
+ if err != nil {
+ return
+ }
+
+ verifier, err = os.ReadFile(Path("auth/", name, "/verifier"))
+ if err != nil {
+ return
+ }
+
+ a.updateTimestamp(name)
+ return
+}
+
+// SetPasswd creates a password entry if necessary
+// and sets the password of a user.
+func (a authFiles) SetPasswd(name string, salt, verifier []byte) error {
+ os.Mkdir(Path("auth"), 0700)
+ os.Mkdir(Path("auth/", name), 0700)
+
+ if err := os.WriteFile(Path("auth/", name, "/salt"), salt, 0600); err != nil {
+ return err
+ }
+
+ if err := os.WriteFile(Path("auth/", name, "/verifier"), verifier, 0600); err != nil {
+ return err
+ }
+
+ a.updateTimestamp(name)
+ return nil
+}
+
+// Timestamp returns the last time an authentication entry was accessed
+// or an error.
+func (a authFiles) Timestamp(name string) (time.Time, error) {
+ os.Mkdir(Path("auth"), 0700)
+
+ info, err := os.Stat(Path("auth/", name, "/timestamp"))
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ return info.ModTime(), nil
+}
+
+// Import deletes all users and adds the passed users.
+func (a authFiles) Import(in []user) {
+ os.Mkdir(Path("auth"), 0700)
+
+ for _, u := range in {
+ a.SetPasswd(u.name, u.salt, u.verifier)
+ os.Chtimes(Path("auth/", u.name, "/timestamp"), u.timestamp, u.timestamp)
+ }
+}
+
+// Export returns data that can be processed by Import
+// or an error.
+func (a authFiles) Export() ([]user, error) {
+ dir, err := os.ReadDir(Path("auth"))
+ if err != nil {
+ return nil, err
+ }
+
+ var out []user
+ for _, f := range dir {
+ u := user{name: f.Name()}
+
+ u.timestamp, err = a.Timestamp(u.name)
+ if err != nil {
+ return nil, err
+ }
+
+ u.salt, u.verifier, err = a.Passwd(u.name)
+ if err != nil {
+ return nil, err
+ }
+
+ out = append(out, u)
+ }
+
+ return out, nil
+}
+
+// Ban adds a ban entry for a network address and an associated name.
+func (a authFiles) Ban(addr, name string) error {
+ os.Mkdir(Path("ban"), 0700)
+ return os.WriteFile(Path("ban/", addr), []byte(name), 0600)
+}
+
+// Unban deletes a ban entry. It accepts both network addresses
+// and player names.
+func (a authFiles) Unban(id string) error {
+ os.Mkdir(Path("ban"), 0700)
+
+ if err := os.Remove(Path("ban/", id)); err != nil {
+ if os.IsNotExist(err) {
+ dir, err := os.ReadDir(Path("ban"))
+ if err != nil {
+ return err
+ }
+
+ for _, f := range dir {
+ name, err := os.ReadFile(Path("ban/", f.Name()))
+ if err != nil {
+ return err
+ }
+
+ if string(name) == id {
+ return os.Remove(Path("ban/", f.Name()))
+ break
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+// Banned reports whether a network address is banned.
+func (a authFiles) Banned(addr *net.UDPAddr) bool {
+ os.Mkdir(Path("ban"), 0700)
+
+ _, err := os.Stat(Path("ban/", addr.IP.String()))
+ if os.IsNotExist(err) {
+ return false
+ }
+
+ return true
+}
+
+// ImportBans deletes all ban entries and adds the passed entries.
+func (a authFiles) ImportBans(in []ban) {
+ os.Mkdir(Path("ban"), 0700)
+
+ for _, b := range in {
+ a.Ban(b.addr, b.name)
+ }
+}
+
+// ExportBans returns data that can be processed by ImportBans
+// or an error,
+func (a authFiles) ExportBans() ([]ban, error) {
+ os.Mkdir(Path("ban"), 0700)
+
+ dir, err := os.ReadDir(Path("ban"))
+ if err != nil {
+ return nil, err
+ }
+
+ var out []ban
+ for _, f := range dir {
+ b := ban{addr: f.Name()}
+
+ name, err := os.ReadFile(Path("ban/", f.Name()))
+ if err != nil {
+ return nil, err
+ }
+
+ b.name = string(name)
+ out = append(out, b)
+ }
+
+ return out, nil
+}
+
+func (a authFiles) updateTimestamp(name string) {
+ os.Mkdir(Path("auth"), 0700)
+
+ t := time.Now().Local()
+ os.Chtimes(Path("auth/", name, "/timestamp"), t, t)
+}