summaryrefslogtreecommitdiff
path: root/deprecated-webircgateway/pkg/webircgateway/config.go
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-11-02 15:29:28 +0800
committerMistivia <i@mistivia.com>2025-11-02 15:29:28 +0800
commit9f42c2d5f911cb4e215d7873221e642ce7df4d61 (patch)
tree6dac90a889a7402a9556d3d1bcc5cb53cdb9f123 /deprecated-webircgateway/pkg/webircgateway/config.go
parentfb2d9de539b660a261af19b1cbcceb7ee7980cb1 (diff)
deprecate webircdateway and ngircd
Diffstat (limited to 'deprecated-webircgateway/pkg/webircgateway/config.go')
-rw-r--r--deprecated-webircgateway/pkg/webircgateway/config.go385
1 files changed, 385 insertions, 0 deletions
diff --git a/deprecated-webircgateway/pkg/webircgateway/config.go b/deprecated-webircgateway/pkg/webircgateway/config.go
new file mode 100644
index 0000000..019d955
--- /dev/null
+++ b/deprecated-webircgateway/pkg/webircgateway/config.go
@@ -0,0 +1,385 @@
+package webircgateway
+
+import (
+ "errors"
+ "net"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "github.com/gobwas/glob"
+ "gopkg.in/ini.v1"
+)
+
+// ConfigUpstream - An upstream config
+type ConfigUpstream struct {
+ // Plugins may assign an arbitary address to an upstream network
+ NetworkCommonAddress string
+ Hostname string
+ Port int
+ TLS bool
+ Timeout int
+ Throttle int
+ WebircPassword string
+ ServerPassword string
+ GatewayName string
+ Proxy *ConfigProxy
+ Protocol string
+ LocalAddr string
+}
+
+// ConfigServer - A web server config
+type ConfigServer struct {
+ LocalAddr string
+ BindMode os.FileMode
+ Port int
+ TLS bool
+ CertFile string
+ KeyFile string
+ LetsEncryptCacheDir string
+}
+
+type ConfigProxy struct {
+ Type string
+ Hostname string
+ Port int
+ TLS bool
+ Username string
+ Interface string
+}
+
+// Config - Config options for the running app
+type Config struct {
+ gateway *Gateway
+ ConfigFile string
+ LogLevel int
+ Gateway bool
+ GatewayName string
+ GatewayWhitelist []glob.Glob
+ GatewayThrottle int
+ GatewayTimeout int
+ GatewayWebircPassword map[string]string
+ GatewayProtocol string
+ GatewayLocalAddr string
+ Proxy ConfigServer
+ Upstreams []ConfigUpstream
+ Servers []ConfigServer
+ ServerTransports []string
+ RemoteOrigins []glob.Glob
+ ReverseProxies []net.IPNet
+ Webroot string
+ ClientRealname string
+ ClientUsername string
+ ClientHostname string
+ Identd bool
+ RequiresVerification bool
+ SendQuitOnClientClose string
+ ReCaptchaURL string
+ ReCaptchaSecret string
+ ReCaptchaKey string
+ Secret string
+ Plugins []string
+ DnsblServers []string
+ // DnsblAction - "deny" = deny the connection. "verify" = require verification
+ DnsblAction string
+}
+
+func NewConfig(gateway *Gateway) *Config {
+ return &Config{gateway: gateway}
+}
+
+// ConfigResolvePath - If relative, resolve a path to it's full absolute path relative to the config file
+func (c *Config) ResolvePath(path string) string {
+ // Absolute paths should stay as they are
+ if path[0:1] == "/" {
+ return path
+ }
+
+ resolved := filepath.Dir(c.ConfigFile)
+ resolved = filepath.Clean(resolved + "/" + path)
+ return resolved
+}
+
+func (c *Config) SetConfigFile(configFile string) {
+ // Config paths starting with $ is executed rather than treated as a path
+ if strings.HasPrefix(configFile, "$ ") {
+ c.ConfigFile = configFile
+ } else {
+ c.ConfigFile, _ = filepath.Abs(configFile)
+ }
+}
+
+// CurrentConfigFile - Return the full path or command for the config file in use
+func (c *Config) CurrentConfigFile() string {
+ return c.ConfigFile
+}
+
+func (c *Config) Load() error {
+ var configSrc interface{}
+
+ if strings.HasPrefix(c.ConfigFile, "$ ") {
+ cmdRawOut, err := exec.Command("sh", "-c", c.ConfigFile[2:]).Output()
+ if err != nil {
+ return err
+ }
+
+ configSrc = cmdRawOut
+ } else {
+ configSrc = c.ConfigFile
+ }
+
+ cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true, SpaceBeforeInlineComment: true}, configSrc)
+ if err != nil {
+ return err
+ }
+
+ // Clear the existing config
+ c.Gateway = false
+ c.GatewayWebircPassword = make(map[string]string)
+ c.Proxy = ConfigServer{}
+ c.Upstreams = []ConfigUpstream{}
+ c.Servers = []ConfigServer{}
+ c.ServerTransports = []string{}
+ c.RemoteOrigins = []glob.Glob{}
+ c.GatewayWhitelist = []glob.Glob{}
+ c.ReverseProxies = []net.IPNet{}
+ c.Webroot = ""
+ c.ReCaptchaURL = ""
+ c.ReCaptchaSecret = ""
+ c.ReCaptchaKey = ""
+ c.RequiresVerification = false
+ c.Secret = ""
+ c.SendQuitOnClientClose = ""
+ c.ClientRealname = ""
+ c.ClientUsername = ""
+ c.ClientHostname = ""
+ c.DnsblServers = []string{}
+ c.DnsblAction = ""
+
+ for _, section := range cfg.Sections() {
+ if strings.Index(section.Name(), "DEFAULT") == 0 {
+ c.LogLevel = section.Key("logLevel").MustInt(3)
+ if c.LogLevel < 1 || c.LogLevel > 3 {
+ c.gateway.Log(3, "Config option logLevel must be between 1-3. Setting default value of 3.")
+ c.LogLevel = 3
+ }
+
+ c.Identd = section.Key("identd").MustBool(false)
+
+ c.GatewayName = section.Key("gateway_name").MustString("")
+ if strings.Contains(c.GatewayName, " ") {
+ c.gateway.Log(3, "Config option gateway_name must not contain spaces")
+ c.GatewayName = ""
+ }
+
+ c.Secret = section.Key("secret").MustString("")
+ c.SendQuitOnClientClose = section.Key("send_quit_on_client_close").MustString("Connection closed")
+ }
+
+ if section.Name() == "verify" {
+ captchaSecret := section.Key("recaptcha_secret").MustString("")
+ captchaKey := section.Key("recaptcha_key").MustString("")
+ if captchaSecret != "" && captchaKey != "" {
+ c.RequiresVerification = section.Key("required").MustBool(false)
+ c.ReCaptchaSecret = captchaSecret
+ }
+ c.ReCaptchaURL = section.Key("recaptcha_url").MustString("https://www.google.com/recaptcha/api/siteverify")
+ }
+
+ if section.Name() == "dnsbl" {
+ c.DnsblAction = section.Key("action").MustString("")
+ }
+
+ if section.Name() == "dnsbl.servers" {
+ c.DnsblServers = append(c.DnsblServers, section.KeyStrings()...)
+ }
+
+ if section.Name() == "gateway" {
+ c.Gateway = section.Key("enabled").MustBool(false)
+ c.GatewayTimeout = section.Key("timeout").MustInt(10)
+ c.GatewayThrottle = section.Key("throttle").MustInt(2)
+
+ validProtocols := []string{"tcp", "tcp4", "tcp6"}
+ c.GatewayProtocol = stringInSliceOrDefault(section.Key("protocol").MustString(""), "tcp", validProtocols)
+ c.GatewayLocalAddr = section.Key("localaddr").MustString("")
+ }
+
+ if section.Name() == "gateway.webirc" {
+ for _, serverAddr := range section.KeyStrings() {
+ c.GatewayWebircPassword[serverAddr] = section.Key(serverAddr).MustString("")
+ }
+ }
+
+ if strings.Index(section.Name(), "clients") == 0 {
+ c.ClientUsername = section.Key("username").MustString("")
+ c.ClientRealname = section.Key("realname").MustString("")
+ c.ClientHostname = section.Key("hostname").MustString("")
+ }
+
+ if strings.Index(section.Name(), "fileserving") == 0 {
+ if section.Key("enabled").MustBool(false) {
+ c.Webroot = section.Key("webroot").MustString("")
+ }
+ }
+
+ if strings.Index(section.Name(), "server.") == 0 {
+ server := ConfigServer{}
+ server.LocalAddr = confKeyAsString(section.Key("bind"), "127.0.0.1")
+ rawMode := confKeyAsString(section.Key("bind_mode"), "")
+ mode, err := strconv.ParseInt(rawMode, 8, 32)
+ if err != nil {
+ mode = 0755
+ }
+ server.BindMode = os.FileMode(mode)
+ server.Port = confKeyAsInt(section.Key("port"), 80)
+ server.TLS = confKeyAsBool(section.Key("tls"), false)
+ server.CertFile = confKeyAsString(section.Key("cert"), "")
+ server.KeyFile = confKeyAsString(section.Key("key"), "")
+ server.LetsEncryptCacheDir = confKeyAsString(section.Key("letsencrypt_cache"), "")
+
+ if strings.HasSuffix(server.LetsEncryptCacheDir, ".cache") {
+ return errors.New("Syntax has changed. Please update letsencrypt_cache to a directory path (eg ./cache)")
+ }
+
+ c.Servers = append(c.Servers, server)
+ }
+
+ if section.Name() == "proxy" {
+ server := ConfigServer{}
+ server.LocalAddr = confKeyAsString(section.Key("bind"), "0.0.0.0")
+ server.Port = confKeyAsInt(section.Key("port"), 7999)
+ c.Proxy = server
+ }
+
+ if strings.Index(section.Name(), "upstream.") == 0 {
+ upstream := ConfigUpstream{}
+
+ validProtocols := []string{"tcp", "tcp4", "tcp6", "unix"}
+ upstream.Protocol = stringInSliceOrDefault(section.Key("protocol").MustString(""), "tcp", validProtocols)
+
+ hostname := section.Key("hostname").MustString("127.0.0.1")
+ if strings.HasPrefix(strings.ToLower(hostname), "unix:") {
+ upstream.Protocol = "unix"
+ upstream.Hostname = hostname[5:]
+ } else {
+ upstream.Hostname = hostname
+ upstream.Port = section.Key("port").MustInt(6667)
+ upstream.TLS = section.Key("tls").MustBool(false)
+ }
+
+ upstream.Timeout = section.Key("timeout").MustInt(10)
+ upstream.Throttle = section.Key("throttle").MustInt(2)
+ upstream.WebircPassword = section.Key("webirc").MustString("")
+ upstream.ServerPassword = section.Key("serverpassword").MustString("")
+ upstream.LocalAddr = section.Key("localaddr").MustString("")
+
+ upstream.GatewayName = section.Key("gateway_name").MustString("")
+ if strings.Contains(upstream.GatewayName, " ") {
+ c.gateway.Log(3, "Config option gateway_name must not contain spaces")
+ upstream.GatewayName = ""
+ }
+
+ upstream.NetworkCommonAddress = section.Key("network_common_address").MustString("")
+
+ c.Upstreams = append(c.Upstreams, upstream)
+ }
+
+ // "engines" is now legacy naming
+ if section.Name() == "engines" || section.Name() == "transports" {
+ for _, transport := range section.KeyStrings() {
+ c.ServerTransports = append(c.ServerTransports, strings.Trim(transport, "\n"))
+ }
+ }
+
+ if strings.Index(section.Name(), "plugins") == 0 {
+ for _, plugin := range section.KeyStrings() {
+ c.Plugins = append(c.Plugins, strings.Trim(plugin, "\n"))
+ }
+ }
+
+ if strings.Index(section.Name(), "allowed_origins") == 0 {
+ for _, origin := range section.KeyStrings() {
+ match, err := glob.Compile(origin)
+ if err != nil {
+ c.gateway.Log(3, "Config section allowed_origins has invalid match, "+origin)
+ continue
+ }
+ c.RemoteOrigins = append(c.RemoteOrigins, match)
+ }
+ }
+
+ if strings.Index(section.Name(), "gateway.whitelist") == 0 {
+ for _, origin := range section.KeyStrings() {
+ match, err := glob.Compile(origin)
+ if err != nil {
+ c.gateway.Log(3, "Config section gateway.whitelist has invalid match, "+origin)
+ continue
+ }
+ c.GatewayWhitelist = append(c.GatewayWhitelist, match)
+ }
+ }
+
+ if strings.Index(section.Name(), "reverse_proxies") == 0 {
+ for _, cidrRange := range section.KeyStrings() {
+ _, validRange, cidrErr := net.ParseCIDR(cidrRange)
+ if cidrErr != nil {
+ c.gateway.Log(3, "Config section reverse_proxies has invalid entry, "+cidrRange)
+ continue
+ }
+ c.ReverseProxies = append(c.ReverseProxies, *validRange)
+ }
+ }
+ }
+
+ return nil
+}
+
+func confKeyAsString(key *ini.Key, def string) string {
+ val := def
+
+ str := key.String()
+ if len(str) > 1 && str[:1] == "$" {
+ val = os.Getenv(str[1:])
+ } else {
+ val = key.MustString(def)
+ }
+
+ return val
+}
+
+func confKeyAsInt(key *ini.Key, def int) int {
+ val := def
+
+ str := key.String()
+ if len(str) > 1 && str[:1] == "$" {
+ envVal := os.Getenv(str[1:])
+ envValInt, err := strconv.Atoi(envVal)
+ if err == nil {
+ val = envValInt
+ }
+ } else {
+ val = key.MustInt(def)
+ }
+
+ return val
+}
+
+func confKeyAsBool(key *ini.Key, def bool) bool {
+ val := def
+
+ str := key.String()
+ if len(str) > 1 && str[:1] == "$" {
+ envVal := os.Getenv(str[1:])
+ if envVal == "0" || envVal == "false" || envVal == "no" {
+ val = false
+ } else {
+ val = true
+ }
+ } else {
+ val = key.MustBool(def)
+ }
+
+ return val
+}