mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-25 13:29:27 +01:00
add sasl-only config option
This commit is contained in:
parent
ea07d99074
commit
1c23af8767
@ -456,7 +456,7 @@ func (am *AccountManager) setPassword(account string, password string) (err erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (am *AccountManager) dispatchCallback(client *Client, casefoldedAccount string, callbackNamespace string, callbackValue string) (string, error) {
|
func (am *AccountManager) dispatchCallback(client *Client, casefoldedAccount string, callbackNamespace string, callbackValue string) (string, error) {
|
||||||
if callbackNamespace == "*" || callbackNamespace == "none" {
|
if callbackNamespace == "*" || callbackNamespace == "none" || callbackNamespace == "admin" {
|
||||||
return "", nil
|
return "", nil
|
||||||
} else if callbackNamespace == "mailto" {
|
} else if callbackNamespace == "mailto" {
|
||||||
return am.dispatchMailtoCallback(client, casefoldedAccount, callbackValue)
|
return am.dispatchMailtoCallback(client, casefoldedAccount, callbackValue)
|
||||||
@ -590,7 +590,9 @@ func (am *AccountManager) Verify(client *Client, account string, code string) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
am.Login(client, clientAccount)
|
if client != nil {
|
||||||
|
am.Login(client, clientAccount)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,10 +32,6 @@ const (
|
|||||||
IRCv3TimestampFormat = "2006-01-02T15:04:05.000Z"
|
IRCv3TimestampFormat = "2006-01-02T15:04:05.000Z"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
LoopbackIP = net.ParseIP("127.0.0.1")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ResumeDetails is a place to stash data at various stages of
|
// ResumeDetails is a place to stash data at various stages of
|
||||||
// the resume process: when handling the RESUME command itself,
|
// the resume process: when handling the RESUME command itself,
|
||||||
// when completing the registration, and when rejoining channels.
|
// when completing the registration, and when rejoining channels.
|
||||||
@ -55,7 +51,6 @@ type Client struct {
|
|||||||
account string
|
account string
|
||||||
accountName string // display name of the account: uncasefolded, '*' if not logged in
|
accountName string // display name of the account: uncasefolded, '*' if not logged in
|
||||||
atime time.Time
|
atime time.Time
|
||||||
authorized bool
|
|
||||||
awayMessage string
|
awayMessage string
|
||||||
capabilities *caps.Set
|
capabilities *caps.Set
|
||||||
capState caps.State
|
capState caps.State
|
||||||
@ -88,12 +83,14 @@ type Client struct {
|
|||||||
quitMessage string
|
quitMessage string
|
||||||
rawHostname string
|
rawHostname string
|
||||||
realname string
|
realname string
|
||||||
|
realIP net.IP
|
||||||
registered bool
|
registered bool
|
||||||
resumeDetails *ResumeDetails
|
resumeDetails *ResumeDetails
|
||||||
resumeToken string
|
resumeToken string
|
||||||
saslInProgress bool
|
saslInProgress bool
|
||||||
saslMechanism string
|
saslMechanism string
|
||||||
saslValue string
|
saslValue string
|
||||||
|
sentPassCommand bool
|
||||||
server *Server
|
server *Server
|
||||||
skeleton string
|
skeleton string
|
||||||
socket *Socket
|
socket *Socket
|
||||||
@ -131,7 +128,6 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) {
|
|||||||
socket := NewSocket(conn, fullLineLenLimit*2, config.Server.MaxSendQBytes)
|
socket := NewSocket(conn, fullLineLenLimit*2, config.Server.MaxSendQBytes)
|
||||||
client := &Client{
|
client := &Client{
|
||||||
atime: now,
|
atime: now,
|
||||||
authorized: server.Password() == nil,
|
|
||||||
capabilities: caps.NewSet(),
|
capabilities: caps.NewSet(),
|
||||||
capState: caps.NoneState,
|
capState: caps.NoneState,
|
||||||
capVersion: caps.Cap301,
|
capVersion: caps.Cap301,
|
||||||
@ -152,6 +148,12 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) {
|
|||||||
}
|
}
|
||||||
client.languages = server.languages.Default()
|
client.languages = server.languages.Default()
|
||||||
|
|
||||||
|
remoteAddr := conn.RemoteAddr()
|
||||||
|
client.realIP = utils.AddrToIP(remoteAddr)
|
||||||
|
if client.realIP == nil {
|
||||||
|
server.logger.Error("internal", "bad remote address", remoteAddr.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
client.recomputeMaxlens()
|
client.recomputeMaxlens()
|
||||||
if isTLS {
|
if isTLS {
|
||||||
client.SetMode(modes.TLS, true)
|
client.SetMode(modes.TLS, true)
|
||||||
@ -159,7 +161,7 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) {
|
|||||||
// error is not useful to us here anyways so we can ignore it
|
// error is not useful to us here anyways so we can ignore it
|
||||||
client.certfp, _ = client.socket.CertFP()
|
client.certfp, _ = client.socket.CertFP()
|
||||||
}
|
}
|
||||||
if config.Server.CheckIdent && !utils.AddrIsUnix(conn.RemoteAddr()) {
|
if config.Server.CheckIdent && !utils.AddrIsUnix(remoteAddr) {
|
||||||
_, serverPortString, err := net.SplitHostPort(conn.LocalAddr().String())
|
_, serverPortString, err := net.SplitHostPort(conn.LocalAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.logger.Error("internal", "bad server address", err.Error())
|
server.logger.Error("internal", "bad server address", err.Error())
|
||||||
@ -196,6 +198,16 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) {
|
|||||||
go client.run()
|
go client.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) isAuthorized(config *Config) bool {
|
||||||
|
saslSent := client.account != ""
|
||||||
|
passRequirementMet := (config.Server.passwordBytes == nil) || client.sentPassCommand || (config.Accounts.SkipServerPassword && saslSent)
|
||||||
|
if !passRequirementMet {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
saslRequirementMet := !config.Accounts.RequireSasl.Enabled || saslSent || utils.IPInNets(client.IP(), config.Accounts.RequireSasl.exemptedNets)
|
||||||
|
return saslRequirementMet
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) resetFakelag() {
|
func (client *Client) resetFakelag() {
|
||||||
fakelag := func() *Fakelag {
|
fakelag := func() *Fakelag {
|
||||||
if client.HasRoleCapabs("nofakelag") {
|
if client.HasRoleCapabs("nofakelag") {
|
||||||
@ -218,14 +230,13 @@ func (client *Client) resetFakelag() {
|
|||||||
|
|
||||||
// IP returns the IP address of this client.
|
// IP returns the IP address of this client.
|
||||||
func (client *Client) IP() net.IP {
|
func (client *Client) IP() net.IP {
|
||||||
|
client.stateMutex.RLock()
|
||||||
|
defer client.stateMutex.RUnlock()
|
||||||
|
|
||||||
if client.proxiedIP != nil {
|
if client.proxiedIP != nil {
|
||||||
return client.proxiedIP
|
return client.proxiedIP
|
||||||
}
|
}
|
||||||
if ip := utils.AddrToIP(client.socket.conn.RemoteAddr()); ip != nil {
|
return client.realIP
|
||||||
return ip
|
|
||||||
}
|
|
||||||
// unix domain socket that hasn't issued PROXY/WEBIRC yet. YOLO
|
|
||||||
return LoopbackIP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPString returns the IP address of this client as a string.
|
// IPString returns the IP address of this client as a string.
|
||||||
@ -296,7 +307,7 @@ func (client *Client) run() {
|
|||||||
|
|
||||||
// Set the hostname for this client
|
// Set the hostname for this client
|
||||||
// (may be overridden by a later PROXY command from stunnel)
|
// (may be overridden by a later PROXY command from stunnel)
|
||||||
client.rawHostname = utils.AddrLookupHostname(client.socket.conn.RemoteAddr())
|
client.rawHostname = utils.LookupHostname(client.realIP.String())
|
||||||
|
|
||||||
firstLine := true
|
firstLine := true
|
||||||
|
|
||||||
|
@ -54,7 +54,9 @@ func (cmd *Command) Run(server *Server, client *Client, msg ircmsg.IrcMessage) b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// most servers do this only for PING/PONG, but we'll do it for any command:
|
// most servers do this only for PING/PONG, but we'll do it for any command:
|
||||||
client.idletimer.Touch()
|
if client.registered {
|
||||||
|
client.idletimer.Touch()
|
||||||
|
}
|
||||||
|
|
||||||
if !cmd.leaveClientIdle {
|
if !cmd.leaveClientIdle {
|
||||||
client.Active()
|
client.Active()
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -54,7 +55,12 @@ func (conf *TLSListenConfig) Config() (*tls.Config, error) {
|
|||||||
type AccountConfig struct {
|
type AccountConfig struct {
|
||||||
Registration AccountRegistrationConfig
|
Registration AccountRegistrationConfig
|
||||||
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
||||||
LoginThrottling struct {
|
RequireSasl struct {
|
||||||
|
Enabled bool
|
||||||
|
Exempted []string
|
||||||
|
exemptedNets []net.IPNet
|
||||||
|
} `yaml:"require-sasl"`
|
||||||
|
LoginThrottling struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
MaxAttempts int `yaml:"max-attempts"`
|
MaxAttempts int `yaml:"max-attempts"`
|
||||||
@ -261,8 +267,9 @@ type Config struct {
|
|||||||
STS STSConfig
|
STS STSConfig
|
||||||
CheckIdent bool `yaml:"check-ident"`
|
CheckIdent bool `yaml:"check-ident"`
|
||||||
MOTD string
|
MOTD string
|
||||||
MOTDFormatting bool `yaml:"motd-formatting"`
|
MOTDFormatting bool `yaml:"motd-formatting"`
|
||||||
ProxyAllowedFrom []string `yaml:"proxy-allowed-from"`
|
ProxyAllowedFrom []string `yaml:"proxy-allowed-from"`
|
||||||
|
proxyAllowedFromNets []net.IPNet
|
||||||
WebIRC []webircConfig `yaml:"webirc"`
|
WebIRC []webircConfig `yaml:"webirc"`
|
||||||
MaxSendQString string `yaml:"max-sendq"`
|
MaxSendQString string `yaml:"max-sendq"`
|
||||||
MaxSendQBytes int
|
MaxSendQBytes int
|
||||||
@ -595,6 +602,16 @@ func LoadConfig(filename string) (config *Config, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.Accounts.RequireSasl.exemptedNets, err = utils.ParseNetList(config.Accounts.RequireSasl.Exempted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse require-sasl exempted nets: %v", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Server.proxyAllowedFromNets, err = utils.ParseNetList(config.Server.ProxyAllowedFrom)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse proxy-allowed-from nets: %v", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
rawRegexp := config.Accounts.VHosts.ValidRegexpRaw
|
rawRegexp := config.Accounts.VHosts.ValidRegexpRaw
|
||||||
if rawRegexp != "" {
|
if rawRegexp != "" {
|
||||||
regexp, err := regexp.Compile(rawRegexp)
|
regexp, err := regexp.Compile(rawRegexp)
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/oragono/oragono/irc/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LimiterConfig controls the automated connection limits.
|
// LimiterConfig controls the automated connection limits.
|
||||||
@ -36,8 +38,6 @@ type Limiter struct {
|
|||||||
// population holds IP -> count of clients connected from there
|
// population holds IP -> count of clients connected from there
|
||||||
population map[string]int
|
population map[string]int
|
||||||
|
|
||||||
// exemptedIPs holds IPs that are exempt from limits
|
|
||||||
exemptedIPs map[string]bool
|
|
||||||
// exemptedNets holds networks that are exempt from limits
|
// exemptedNets holds networks that are exempt from limits
|
||||||
exemptedNets []net.IPNet
|
exemptedNets []net.IPNet
|
||||||
}
|
}
|
||||||
@ -67,14 +67,9 @@ func (cl *Limiter) AddClient(addr net.IP, force bool) error {
|
|||||||
|
|
||||||
// check exempted lists
|
// check exempted lists
|
||||||
// we don't track populations for exempted addresses or nets - this is by design
|
// we don't track populations for exempted addresses or nets - this is by design
|
||||||
if cl.exemptedIPs[addr.String()] {
|
if utils.IPInNets(addr, cl.exemptedNets) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, ex := range cl.exemptedNets {
|
|
||||||
if ex.Contains(addr) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check population
|
// check population
|
||||||
cl.maskAddr(addr)
|
cl.maskAddr(addr)
|
||||||
@ -121,21 +116,9 @@ func NewLimiter() *Limiter {
|
|||||||
// ApplyConfig atomically applies a config update to a connection limit handler
|
// ApplyConfig atomically applies a config update to a connection limit handler
|
||||||
func (cl *Limiter) ApplyConfig(config LimiterConfig) error {
|
func (cl *Limiter) ApplyConfig(config LimiterConfig) error {
|
||||||
// assemble exempted nets
|
// assemble exempted nets
|
||||||
exemptedIPs := make(map[string]bool)
|
exemptedNets, err := utils.ParseNetList(config.Exempted)
|
||||||
var exemptedNets []net.IPNet
|
if err != nil {
|
||||||
for _, cidr := range config.Exempted {
|
return fmt.Errorf("Could not parse limiter exemption list: %v", err.Error())
|
||||||
ipaddr := net.ParseIP(cidr)
|
|
||||||
_, netaddr, err := net.ParseCIDR(cidr)
|
|
||||||
|
|
||||||
if ipaddr == nil && err != nil {
|
|
||||||
return fmt.Errorf("Could not parse exempted IP/network [%s]", cidr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipaddr != nil {
|
|
||||||
exemptedIPs[ipaddr.String()] = true
|
|
||||||
} else {
|
|
||||||
exemptedNets = append(exemptedNets, *netaddr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cl.Lock()
|
cl.Lock()
|
||||||
@ -151,7 +134,6 @@ func (cl *Limiter) ApplyConfig(config LimiterConfig) error {
|
|||||||
if cl.subnetLimit == 0 && config.IPsPerSubnet != 0 {
|
if cl.subnetLimit == 0 && config.IPsPerSubnet != 0 {
|
||||||
cl.subnetLimit = config.IPsPerSubnet
|
cl.subnetLimit = config.IPsPerSubnet
|
||||||
}
|
}
|
||||||
cl.exemptedIPs = exemptedIPs
|
|
||||||
cl.exemptedNets = exemptedNets
|
cl.exemptedNets = exemptedNets
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/oragono/oragono/irc/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ThrottlerConfig controls the automated connection throttling.
|
// ThrottlerConfig controls the automated connection throttling.
|
||||||
@ -82,8 +84,6 @@ type Throttler struct {
|
|||||||
banDuration time.Duration
|
banDuration time.Duration
|
||||||
banMessage string
|
banMessage string
|
||||||
|
|
||||||
// exemptedIPs holds IPs that are exempt from limits
|
|
||||||
exemptedIPs map[string]bool
|
|
||||||
// exemptedNets holds networks that are exempt from limits
|
// exemptedNets holds networks that are exempt from limits
|
||||||
exemptedNets []net.IPNet
|
exemptedNets []net.IPNet
|
||||||
}
|
}
|
||||||
@ -126,14 +126,9 @@ func (ct *Throttler) AddClient(addr net.IP) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check exempted lists
|
// check exempted lists
|
||||||
if ct.exemptedIPs[addr.String()] {
|
if utils.IPInNets(addr, ct.exemptedNets) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, ex := range ct.exemptedNets {
|
|
||||||
if ex.Contains(addr) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check throttle
|
// check throttle
|
||||||
ct.maskAddr(addr)
|
ct.maskAddr(addr)
|
||||||
@ -184,21 +179,9 @@ func NewThrottler() *Throttler {
|
|||||||
// ApplyConfig atomically applies a config update to a throttler
|
// ApplyConfig atomically applies a config update to a throttler
|
||||||
func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error {
|
func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error {
|
||||||
// assemble exempted nets
|
// assemble exempted nets
|
||||||
exemptedIPs := make(map[string]bool)
|
exemptedNets, err := utils.ParseNetList(config.Exempted)
|
||||||
var exemptedNets []net.IPNet
|
if err != nil {
|
||||||
for _, cidr := range config.Exempted {
|
return fmt.Errorf("Could not parse throttle exemption list: %v", err.Error())
|
||||||
ipaddr := net.ParseIP(cidr)
|
|
||||||
_, netaddr, err := net.ParseCIDR(cidr)
|
|
||||||
|
|
||||||
if ipaddr == nil && err != nil {
|
|
||||||
return fmt.Errorf("Could not parse exempted IP/network [%s]", cidr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipaddr != nil {
|
|
||||||
exemptedIPs[ipaddr.String()] = true
|
|
||||||
} else {
|
|
||||||
exemptedNets = append(exemptedNets, *netaddr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.Lock()
|
ct.Lock()
|
||||||
@ -211,7 +194,6 @@ func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error {
|
|||||||
ct.duration = config.Duration
|
ct.duration = config.Duration
|
||||||
ct.banDuration = config.BanDuration
|
ct.banDuration = config.BanDuration
|
||||||
ct.banMessage = config.BanMessage
|
ct.banMessage = config.BanMessage
|
||||||
ct.exemptedIPs = exemptedIPs
|
|
||||||
ct.exemptedNets = exemptedNets
|
ct.exemptedNets = exemptedNets
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -25,6 +25,7 @@ type webircConfig struct {
|
|||||||
Password []byte `yaml:"password-bytes"`
|
Password []byte `yaml:"password-bytes"`
|
||||||
Fingerprint string
|
Fingerprint string
|
||||||
Hosts []string
|
Hosts []string
|
||||||
|
allowedNets []net.IPNet
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate fills out our password or fingerprint.
|
// Populate fills out our password or fingerprint.
|
||||||
@ -36,49 +37,23 @@ func (wc *webircConfig) Populate() (err error) {
|
|||||||
if wc.PasswordString != "" {
|
if wc.PasswordString != "" {
|
||||||
wc.Password, err = decodeLegacyPasswordHash(wc.PasswordString)
|
wc.Password, err = decodeLegacyPasswordHash(wc.PasswordString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
wc.allowedNets, err = utils.ParseNetList(wc.Hosts)
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGatewayAllowed(addr net.Addr, gatewaySpec string) bool {
|
|
||||||
// "localhost" includes any loopback IP or unix domain socket
|
|
||||||
if gatewaySpec == "localhost" {
|
|
||||||
return utils.AddrIsLocal(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
ip := utils.AddrToIP(addr)
|
|
||||||
if ip == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// exact IP match
|
|
||||||
if ip.String() == gatewaySpec {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// CIDR match
|
|
||||||
_, gatewayNet, err := net.ParseCIDR(gatewaySpec)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return gatewayNet.Contains(ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyProxiedIP applies the given IP to the client.
|
// ApplyProxiedIP applies the given IP to the client.
|
||||||
func (client *Client) ApplyProxiedIP(proxiedIP string, tls bool) (success bool) {
|
func (client *Client) ApplyProxiedIP(proxiedIP string, tls bool) (success bool) {
|
||||||
// ensure IP is sane
|
// ensure IP is sane
|
||||||
parsedProxiedIP := net.ParseIP(proxiedIP)
|
parsedProxiedIP := net.ParseIP(proxiedIP).To16()
|
||||||
if parsedProxiedIP == nil {
|
if parsedProxiedIP == nil {
|
||||||
client.Quit(fmt.Sprintf(client.t("Proxied IP address is not valid: [%s]"), proxiedIP))
|
client.Quit(fmt.Sprintf(client.t("Proxied IP address is not valid: [%s]"), proxiedIP))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// undo any mapping of v4 addresses into the v6 space: https://stackoverflow.com/a/1618259
|
|
||||||
// this is how a typical stunnel4 deployment on Linux will handle dual-stack
|
|
||||||
unmappedIP := parsedProxiedIP.To4()
|
|
||||||
if unmappedIP != nil {
|
|
||||||
parsedProxiedIP = unmappedIP
|
|
||||||
}
|
|
||||||
|
|
||||||
isBanned, banMsg := client.server.checkBans(parsedProxiedIP)
|
isBanned, banMsg := client.server.checkBans(parsedProxiedIP)
|
||||||
if isBanned {
|
if isBanned {
|
||||||
client.Quit(banMsg)
|
client.Quit(banMsg)
|
||||||
@ -117,14 +92,12 @@ func handleProxyCommand(server *Server, client *Client, line string) (err error)
|
|||||||
return errBadProxyLine
|
return errBadProxyLine
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, gateway := range server.ProxyAllowedFrom() {
|
if utils.IPInNets(client.realIP, server.Config().Server.proxyAllowedFromNets) {
|
||||||
if isGatewayAllowed(client.socket.conn.RemoteAddr(), gateway) {
|
// assume PROXY connections are always secure
|
||||||
// assume PROXY connections are always secure
|
if client.ApplyProxiedIP(params[2], true) {
|
||||||
if client.ApplyProxiedIP(params[2], true) {
|
return nil
|
||||||
return nil
|
} else {
|
||||||
} else {
|
return errBadProxyLine
|
||||||
return errBadProxyLine
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +32,6 @@ func (server *Server) RecoverFromErrors() bool {
|
|||||||
return *server.Config().Debug.RecoverFromErrors
|
return *server.Config().Debug.RecoverFromErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) ProxyAllowedFrom() []string {
|
|
||||||
return server.Config().Server.ProxyAllowedFrom
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) WebIRCConfig() []webircConfig {
|
|
||||||
return server.Config().Server.WebIRC
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) DefaultChannelModes() modes.Modes {
|
func (server *Server) DefaultChannelModes() modes.Modes {
|
||||||
return server.Config().Channels.defaultModes
|
return server.Config().Channels.defaultModes
|
||||||
}
|
}
|
||||||
@ -170,18 +162,6 @@ func (client *Client) SetAccountName(account string) (changed bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) Authorized() bool {
|
|
||||||
client.stateMutex.RLock()
|
|
||||||
defer client.stateMutex.RUnlock()
|
|
||||||
return client.authorized
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) SetAuthorized(authorized bool) {
|
|
||||||
client.stateMutex.Lock()
|
|
||||||
defer client.stateMutex.Unlock()
|
|
||||||
client.authorized = authorized
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) HasMode(mode modes.Mode) bool {
|
func (client *Client) HasMode(mode modes.Mode) bool {
|
||||||
// client.flags has its own synch
|
// client.flags has its own synch
|
||||||
return client.flags.HasMode(mode)
|
return client.flags.HasMode(mode)
|
||||||
|
@ -323,10 +323,6 @@ func authenticateHandler(server *Server, client *Client, msg ircmsg.IrcMessage,
|
|||||||
// let the SASL handler do its thing
|
// let the SASL handler do its thing
|
||||||
exiting := handler(server, client, client.saslMechanism, data, rb)
|
exiting := handler(server, client, client.saslMechanism, data, rb)
|
||||||
|
|
||||||
if client.LoggedIntoAccount() && server.AccountConfig().SkipServerPassword {
|
|
||||||
client.SetAuthorized(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait 'til SASL is done before emptying the sasl vars
|
// wait 'til SASL is done before emptying the sasl vars
|
||||||
client.saslInProgress = false
|
client.saslInProgress = false
|
||||||
client.saslMechanism = ""
|
client.saslMechanism = ""
|
||||||
@ -516,7 +512,7 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "END":
|
case "END":
|
||||||
if !client.Registered() {
|
if !client.registered {
|
||||||
client.capState = caps.NegotiatedState
|
client.capState = caps.NegotiatedState
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1577,7 +1573,7 @@ func namesHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
|
|
||||||
// NICK <nickname>
|
// NICK <nickname>
|
||||||
func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
if client.Registered() {
|
if client.registered {
|
||||||
performNickChange(server, client, client, msg.Params[0], rb)
|
performNickChange(server, client, client, msg.Params[0], rb)
|
||||||
} else {
|
} else {
|
||||||
client.preregNick = msg.Params[0]
|
client.preregNick = msg.Params[0]
|
||||||
@ -1758,7 +1754,7 @@ func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
|
|
||||||
// PASS <password>
|
// PASS <password>
|
||||||
func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
if client.Registered() {
|
if client.registered {
|
||||||
rb.Add(nil, server.name, ERR_ALREADYREGISTRED, client.nick, client.t("You may not reregister"))
|
rb.Add(nil, server.name, ERR_ALREADYREGISTRED, client.nick, client.t("You may not reregister"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1766,7 +1762,6 @@ func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
// if no password exists, skip checking
|
// if no password exists, skip checking
|
||||||
serverPassword := server.Password()
|
serverPassword := server.Password()
|
||||||
if serverPassword == nil {
|
if serverPassword == nil {
|
||||||
client.SetAuthorized(true)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1778,7 +1773,7 @@ func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
client.SetAuthorized(true)
|
client.sentPassCommand = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1986,7 +1981,7 @@ func resumeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
|
|||||||
oldnick := msg.Params[0]
|
oldnick := msg.Params[0]
|
||||||
token := msg.Params[1]
|
token := msg.Params[1]
|
||||||
|
|
||||||
if client.Registered() {
|
if client.registered {
|
||||||
rb.Add(nil, server.name, ERR_CANNOT_RESUME, oldnick, client.t("Cannot resume connection, connection registration has already been completed"))
|
rb.Add(nil, server.name, ERR_CANNOT_RESUME, oldnick, client.t("Cannot resume connection, connection registration has already been completed"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -2188,7 +2183,7 @@ func unKLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
|
|||||||
|
|
||||||
// USER <username> * 0 <realname>
|
// USER <username> * 0 <realname>
|
||||||
func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
if client.Registered() {
|
if client.registered {
|
||||||
rb.Add(nil, server.name, ERR_ALREADYREGISTRED, client.nick, client.t("You may not reregister"))
|
rb.Add(nil, server.name, ERR_ALREADYREGISTRED, client.nick, client.t("You may not reregister"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -2255,7 +2250,7 @@ func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
|
|||||||
// WEBIRC <password> <gateway> <hostname> <ip> [:flag1 flag2=x flag3]
|
// WEBIRC <password> <gateway> <hostname> <ip> [:flag1 flag2=x flag3]
|
||||||
func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
// only allow unregistered clients to use this command
|
// only allow unregistered clients to use this command
|
||||||
if client.Registered() || client.proxiedIP != nil {
|
if client.registered || client.proxiedIP != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2282,26 +2277,24 @@ func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, info := range server.WebIRCConfig() {
|
givenPassword := []byte(msg.Params[0])
|
||||||
for _, gateway := range info.Hosts {
|
for _, info := range server.Config().Server.WebIRC {
|
||||||
if isGatewayAllowed(client.socket.conn.RemoteAddr(), gateway) {
|
if utils.IPInNets(client.realIP, info.allowedNets) {
|
||||||
// confirm password and/or fingerprint
|
// confirm password and/or fingerprint
|
||||||
givenPassword := msg.Params[0]
|
if 0 < len(info.Password) && bcrypt.CompareHashAndPassword(info.Password, givenPassword) != nil {
|
||||||
if 0 < len(info.Password) && bcrypt.CompareHashAndPassword(info.Password, []byte(givenPassword)) != nil {
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
if 0 < len(info.Fingerprint) && client.certfp != info.Fingerprint {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
proxiedIP := msg.Params[3]
|
|
||||||
// see #211; websocket gateways will wrap ipv6 addresses in square brackets
|
|
||||||
// because IRC parameters can't start with :
|
|
||||||
if strings.HasPrefix(proxiedIP, "[") && strings.HasSuffix(proxiedIP, "]") {
|
|
||||||
proxiedIP = proxiedIP[1 : len(proxiedIP)-1]
|
|
||||||
}
|
|
||||||
return !client.ApplyProxiedIP(proxiedIP, secure)
|
|
||||||
}
|
}
|
||||||
|
if 0 < len(info.Fingerprint) && client.certfp != info.Fingerprint {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
proxiedIP := msg.Params[3]
|
||||||
|
// see #211; websocket gateways will wrap ipv6 addresses in square brackets
|
||||||
|
// because IRC parameters can't start with :
|
||||||
|
if strings.HasPrefix(proxiedIP, "[") && strings.HasSuffix(proxiedIP, "]") {
|
||||||
|
proxiedIP = proxiedIP[1 : len(proxiedIP)-1]
|
||||||
|
}
|
||||||
|
return !client.ApplyProxiedIP(proxiedIP, secure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,11 +83,6 @@ func (it *IdleTimer) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *IdleTimer) Touch() {
|
func (it *IdleTimer) Touch() {
|
||||||
// ignore touches from unregistered clients
|
|
||||||
if !it.client.Registered() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
it.updateIdleDuration()
|
it.updateIdleDuration()
|
||||||
|
|
||||||
it.Lock()
|
it.Lock()
|
||||||
|
@ -5,7 +5,6 @@ package irc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/goshuirc/irc-go/ircfmt"
|
"github.com/goshuirc/irc-go/ircfmt"
|
||||||
)
|
)
|
||||||
@ -123,6 +122,18 @@ SADROP forcibly de-links the given nickname from the attached user account.`,
|
|||||||
enabled: servCmdRequiresAccreg,
|
enabled: servCmdRequiresAccreg,
|
||||||
minParams: 1,
|
minParams: 1,
|
||||||
},
|
},
|
||||||
|
"saregister": {
|
||||||
|
handler: nsSaregisterHandler,
|
||||||
|
help: `Syntax: $bSAREGISTER <username> <password>$b
|
||||||
|
|
||||||
|
SAREGISTER registers an account on someone else's behalf.
|
||||||
|
This is for use in configurations that require SASL for all connections;
|
||||||
|
an administrator can set use this command to set up user accounts.`,
|
||||||
|
helpShort: `$bSAREGISTER$b registers an account on someone else's behalf.`,
|
||||||
|
enabled: servCmdRequiresAccreg,
|
||||||
|
capabs: []string{"accreg"},
|
||||||
|
minParams: 2,
|
||||||
|
},
|
||||||
"unregister": {
|
"unregister": {
|
||||||
handler: nsUnregisterHandler,
|
handler: nsUnregisterHandler,
|
||||||
help: `Syntax: $bUNREGISTER <username> [code]$b
|
help: `Syntax: $bUNREGISTER <username> [code]$b
|
||||||
@ -311,22 +322,12 @@ func nsInfoHandler(server *Server, client *Client, command string, params []stri
|
|||||||
|
|
||||||
func nsRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
// get params
|
// get params
|
||||||
username, email := params[0], params[1]
|
account, email := params[0], params[1]
|
||||||
var passphrase string
|
var passphrase string
|
||||||
if len(params) > 2 {
|
if len(params) > 2 {
|
||||||
passphrase = params[2]
|
passphrase = params[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
if !server.AccountConfig().Registration.Enabled {
|
|
||||||
nsNotice(rb, client.t("Account registration has been disabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if username == "" {
|
|
||||||
nsNotice(rb, client.t("No username supplied"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
certfp := client.certfp
|
certfp := client.certfp
|
||||||
if passphrase == "" && certfp == "" {
|
if passphrase == "" && certfp == "" {
|
||||||
nsNotice(rb, client.t("You need to either supply a passphrase or be connected via TLS with a client cert"))
|
nsNotice(rb, client.t("You need to either supply a passphrase or be connected via TLS with a client cert"))
|
||||||
@ -359,9 +360,6 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get and sanitise account name
|
|
||||||
account := strings.TrimSpace(username)
|
|
||||||
|
|
||||||
err := server.accounts.Register(client, account, callbackNamespace, callbackValue, passphrase, client.certfp)
|
err := server.accounts.Register(client, account, callbackNamespace, callbackValue, passphrase, client.certfp)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if callbackNamespace == "*" {
|
if callbackNamespace == "*" {
|
||||||
@ -381,7 +379,7 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
errMsg := client.t("Could not register")
|
errMsg := client.t("Could not register")
|
||||||
if err == errCertfpAlreadyExists {
|
if err == errCertfpAlreadyExists {
|
||||||
errMsg = client.t("An account already exists for your certificate fingerprint")
|
errMsg = client.t("An account already exists for your certificate fingerprint")
|
||||||
} else if err == errAccountAlreadyRegistered {
|
} else if err == errAccountAlreadyRegistered || err == errAccountAlreadyVerified {
|
||||||
errMsg = client.t("Account already exists")
|
errMsg = client.t("Account already exists")
|
||||||
} else if err == errAccountBadPassphrase {
|
} else if err == errAccountBadPassphrase {
|
||||||
errMsg = client.t("Passphrase contains forbidden characters or is otherwise invalid")
|
errMsg = client.t("Passphrase contains forbidden characters or is otherwise invalid")
|
||||||
@ -391,6 +389,29 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nsSaregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
|
account, passphrase := params[0], params[1]
|
||||||
|
err := server.accounts.Register(nil, account, "admin", "", passphrase, "")
|
||||||
|
if err == nil {
|
||||||
|
err = server.accounts.Verify(nil, account, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
var errMsg string
|
||||||
|
if err == errAccountAlreadyRegistered || err == errAccountAlreadyVerified {
|
||||||
|
errMsg = client.t("Account already exists")
|
||||||
|
} else if err == errAccountBadPassphrase {
|
||||||
|
errMsg = client.t("Passphrase contains forbidden characters or is otherwise invalid")
|
||||||
|
} else {
|
||||||
|
server.logger.Error("services", "unknown error from saregister", err.Error())
|
||||||
|
errMsg = client.t("Could not register")
|
||||||
|
}
|
||||||
|
nsNotice(rb, errMsg)
|
||||||
|
} else {
|
||||||
|
nsNotice(rb, fmt.Sprintf(client.t("Successfully registered account %s"), account))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func nsUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
username := params[0]
|
username := params[0]
|
||||||
var verificationCode string
|
var verificationCode string
|
||||||
|
@ -381,7 +381,7 @@ func (server *Server) generateMessageID() string {
|
|||||||
//
|
//
|
||||||
|
|
||||||
func (server *Server) tryRegister(c *Client) {
|
func (server *Server) tryRegister(c *Client) {
|
||||||
if c.Registered() {
|
if c.registered {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,9 +389,10 @@ func (server *Server) tryRegister(c *Client) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// client MUST send PASS (or AUTHENTICATE, if skip-server-password is set)
|
// client MUST send PASS if necessary, or authenticate with SASL if necessary,
|
||||||
// before completing the other registration commands
|
// before completing the other registration commands
|
||||||
if !c.Authorized() {
|
config := server.Config()
|
||||||
|
if !c.isAuthorized(config) {
|
||||||
c.Quit(c.t("Bad password"))
|
c.Quit(c.t("Bad password"))
|
||||||
c.destroy(false)
|
c.destroy(false)
|
||||||
return
|
return
|
||||||
|
@ -11,43 +11,27 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// subnet mask for an ipv6 /128:
|
// subnet mask for an ipv6 /128:
|
||||||
mask128 = net.CIDRMask(128, 128)
|
mask128 = net.CIDRMask(128, 128)
|
||||||
|
IPv4LoopbackAddress = net.ParseIP("127.0.0.1").To16()
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPString returns a simple IP string from the given net.Addr.
|
|
||||||
func IPString(addr net.Addr) string {
|
|
||||||
addrStr := addr.String()
|
|
||||||
ipaddr, _, err := net.SplitHostPort(addrStr)
|
|
||||||
//TODO(dan): Why is this needed, does this happen?
|
|
||||||
if err != nil {
|
|
||||||
return addrStr
|
|
||||||
}
|
|
||||||
return ipaddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddrLookupHostname returns the hostname (if possible) or address for the given `net.Addr`.
|
|
||||||
func AddrLookupHostname(addr net.Addr) string {
|
|
||||||
if AddrIsUnix(addr) {
|
|
||||||
return "localhost"
|
|
||||||
}
|
|
||||||
return LookupHostname(IPString(addr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddrIsLocal returns whether the address is from a trusted local connection (loopback or unix).
|
// AddrIsLocal returns whether the address is from a trusted local connection (loopback or unix).
|
||||||
func AddrIsLocal(addr net.Addr) bool {
|
func AddrIsLocal(addr net.Addr) bool {
|
||||||
if tcpaddr, ok := addr.(*net.TCPAddr); ok {
|
if tcpaddr, ok := addr.(*net.TCPAddr); ok {
|
||||||
return tcpaddr.IP.IsLoopback()
|
return tcpaddr.IP.IsLoopback()
|
||||||
}
|
}
|
||||||
_, ok := addr.(*net.UnixAddr)
|
return AddrIsUnix(addr)
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrToIP returns the IP address for a net.Addr, or nil if it's a unix domain socket.
|
// AddrToIP returns the IP address for a net.Addr; unix domain sockets are treated as IPv4 loopback
|
||||||
func AddrToIP(addr net.Addr) net.IP {
|
func AddrToIP(addr net.Addr) net.IP {
|
||||||
if tcpaddr, ok := addr.(*net.TCPAddr); ok {
|
if tcpaddr, ok := addr.(*net.TCPAddr); ok {
|
||||||
return tcpaddr.IP
|
return tcpaddr.IP.To16()
|
||||||
|
} else if AddrIsUnix(addr) {
|
||||||
|
return IPv4LoopbackAddress
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrIsUnix returns whether the address is a unix domain socket.
|
// AddrIsUnix returns whether the address is a unix domain socket.
|
||||||
@ -100,6 +84,16 @@ func IsHostname(name string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenience to test whether `ip` is contained in any of `nets`.
|
||||||
|
func IPInNets(ip net.IP, nets []net.IPNet) bool {
|
||||||
|
for _, network := range nets {
|
||||||
|
if network.Contains(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// NormalizeIPToNet represents an address (v4 or v6) as the v6 /128 CIDR
|
// NormalizeIPToNet represents an address (v4 or v6) as the v6 /128 CIDR
|
||||||
// containing only it.
|
// containing only it.
|
||||||
func NormalizeIPToNet(addr net.IP) (network net.IPNet) {
|
func NormalizeIPToNet(addr net.IP) (network net.IPNet) {
|
||||||
@ -156,3 +150,25 @@ func NormalizedNetFromString(str string) (result net.IPNet, err error) {
|
|||||||
}
|
}
|
||||||
return NormalizeIPToNet(ip), nil
|
return NormalizeIPToNet(ip), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a list of IPs and nets as they would appear in one of our config
|
||||||
|
// files, e.g., proxy-allowed-from or a throttling exemption list.
|
||||||
|
func ParseNetList(netList []string) (nets []net.IPNet, err error) {
|
||||||
|
var network net.IPNet
|
||||||
|
for _, netStr := range netList {
|
||||||
|
if netStr == "localhost" {
|
||||||
|
ipv4Loopback, _ := NormalizedNetFromString("127.0.0.0/8")
|
||||||
|
ipv6Loopback, _ := NormalizedNetFromString("::1/128")
|
||||||
|
nets = append(nets, ipv4Loopback)
|
||||||
|
nets = append(nets, ipv6Loopback)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
network, err = NormalizedNetFromString(netStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
nets = append(nets, network)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
27
oragono.yaml
27
oragono.yaml
@ -67,8 +67,8 @@ server:
|
|||||||
# if this is true, the motd is escaped using formatting codes like $c, $b, and $i
|
# if this is true, the motd is escaped using formatting codes like $c, $b, and $i
|
||||||
motd-formatting: true
|
motd-formatting: true
|
||||||
|
|
||||||
# addresses/hostnames the PROXY command can be used from
|
# addresses/CIDRs the PROXY command can be used from
|
||||||
# this should be restricted to 127.0.0.1/8 and localhost at most
|
# this should be restricted to 127.0.0.1/8 and ::1/128 (unless you have a good reason)
|
||||||
# you should also add these addresses to the connection limits and throttling exemption lists
|
# you should also add these addresses to the connection limits and throttling exemption lists
|
||||||
proxy-allowed-from:
|
proxy-allowed-from:
|
||||||
# - localhost
|
# - localhost
|
||||||
@ -85,7 +85,7 @@ server:
|
|||||||
# password the gateway uses to connect, made with oragono genpasswd
|
# password the gateway uses to connect, made with oragono genpasswd
|
||||||
password: "$2a$04$sLEFDpIOyUp55e6gTMKbOeroT6tMXTjPFvA0eGvwvImVR9pkwv7ee"
|
password: "$2a$04$sLEFDpIOyUp55e6gTMKbOeroT6tMXTjPFvA0eGvwvImVR9pkwv7ee"
|
||||||
|
|
||||||
# hosts that can use this webirc command
|
# addresses/CIDRs that can use this webirc command
|
||||||
# you should also add these addresses to the connection limits and throttling exemption lists
|
# you should also add these addresses to the connection limits and throttling exemption lists
|
||||||
hosts:
|
hosts:
|
||||||
# - localhost
|
# - localhost
|
||||||
@ -117,9 +117,9 @@ server:
|
|||||||
|
|
||||||
# IPs/networks which are exempted from connection limits
|
# IPs/networks which are exempted from connection limits
|
||||||
exempted:
|
exempted:
|
||||||
- "127.0.0.1"
|
- "localhost"
|
||||||
- "127.0.0.1/8"
|
# - "192.168.1.1"
|
||||||
- "::1/128"
|
# - "2001:0db8::/32"
|
||||||
|
|
||||||
# automated connection throttling
|
# automated connection throttling
|
||||||
connection-throttling:
|
connection-throttling:
|
||||||
@ -145,9 +145,9 @@ server:
|
|||||||
|
|
||||||
# IPs/networks which are exempted from connection limits
|
# IPs/networks which are exempted from connection limits
|
||||||
exempted:
|
exempted:
|
||||||
- "127.0.0.1"
|
- "localhost"
|
||||||
- "127.0.0.1/8"
|
# - "192.168.1.1"
|
||||||
- "::1/128"
|
# - "2001:0db8::/32"
|
||||||
|
|
||||||
# account options
|
# account options
|
||||||
accounts:
|
accounts:
|
||||||
@ -198,6 +198,15 @@ accounts:
|
|||||||
# PASS as well, so it can be configured to authenticate with SASL only.
|
# PASS as well, so it can be configured to authenticate with SASL only.
|
||||||
skip-server-password: false
|
skip-server-password: false
|
||||||
|
|
||||||
|
require-sasl:
|
||||||
|
# if this is enabled, all clients must authenticate with SASL:
|
||||||
|
enabled: false
|
||||||
|
# the following IPs/CIDRs are exempted from this requirement:
|
||||||
|
exempted:
|
||||||
|
- "localhost"
|
||||||
|
# - '127.0.0.2'
|
||||||
|
# - '10.10.0.0/16'
|
||||||
|
|
||||||
# nick-reservation controls how, and whether, nicknames are linked to accounts
|
# nick-reservation controls how, and whether, nicknames are linked to accounts
|
||||||
nick-reservation:
|
nick-reservation:
|
||||||
# is there any enforcement of reserved nicknames?
|
# is there any enforcement of reserved nicknames?
|
||||||
|
Loading…
Reference in New Issue
Block a user