package server import ( "crypto/rand" "encoding/hex" lpra "github.com/x-grk/longpolling-remote-access" ) // Config keys stored in the config table. const ( cfgHostAddress = "host_address" cfgEnrollSecret = "enroll_secret" cfgSetupDone = "setup_done" cfgInstallCode = "install_code" cfgUfwEnabled = "ufw_enabled" ) // DefaultHostAddress is the public URL agents dial by default. It is baked into // the rendered install.sh and can be changed from the settings page. const DefaultHostAddress = "https://REDACTED:8445" // Version is the server build version (see VERSION.txt). It is the newest // version agents update to. var Version = lpra.Version // ensureDefaults seeds the host address and a random enroll secret on first boot. func (db *DB) ensureDefaults() error { host, err := db.GetConfig(cfgHostAddress) if err != nil { return err } if host == "" { if err := db.SetConfig(cfgHostAddress, DefaultHostAddress); err != nil { return err } } secret, err := db.GetConfig(cfgEnrollSecret) if err != nil { return err } if secret == "" { if err := db.SetConfig(cfgEnrollSecret, randToken()); err != nil { return err } } code, err := db.GetConfig(cfgInstallCode) if err != nil { return err } if code == "" { if err := db.SetConfig(cfgInstallCode, shortCode()); err != nil { return err } } return nil } func (db *DB) HostAddress() string { v, _ := db.GetConfig(cfgHostAddress) if v == "" { return DefaultHostAddress } return v } func (db *DB) EnrollSecret() string { v, _ := db.GetConfig(cfgEnrollSecret) return v } // InstallCode returns the short code used for the /i/ install one-liner. func (db *DB) InstallCode() string { v, _ := db.GetConfig(cfgInstallCode) return v } // UfwEnabled reports whether panel-driven ufw integration is on (default yes). func (db *DB) UfwEnabled() bool { v, _ := db.GetConfig(cfgUfwEnabled) return v != "0" } func (db *DB) SetUfwEnabled(on bool) error { if on { return db.SetConfig(cfgUfwEnabled, "1") } return db.SetConfig(cfgUfwEnabled, "0") } func (db *DB) SetupDone() bool { v, _ := db.GetConfig(cfgSetupDone) return v == "1" } func (db *DB) MarkSetupDone() error { return db.SetConfig(cfgSetupDone, "1") } // randToken returns 32 bytes of cryptographic randomness as hex (64 chars). func randToken() string { b := make([]byte, 32) if _, err := rand.Read(b); err != nil { panic("crypto/rand failed: " + err.Error()) } return hex.EncodeToString(b) } // shortCode returns a short, URL-safe, typo-resistant code for install links. // It avoids ambiguous characters (0/O, 1/l/I) so it is easy to read and type. func shortCode() string { const alphabet = "abcdefghjkmnpqrstuvwxyz23456789" b := make([]byte, 7) if _, err := rand.Read(b); err != nil { panic("crypto/rand failed: " + err.Error()) } for i := range b { b[i] = alphabet[int(b[i])%len(alphabet)] } return string(b) }