3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-15 00:19:29 +01:00

Merge pull request #1888 from slingamn/ip_check_script.1

add ip-check-script.exempt-sasl
This commit is contained in:
Shivaram Lingamneni 2022-01-02 07:44:09 -05:00 committed by GitHub
commit c01e686221
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 11 deletions

View File

@ -300,6 +300,9 @@ server:
kill-timeout: 1s kill-timeout: 1s
# how many scripts are allowed to run at once? 0 for no limit: # how many scripts are allowed to run at once? 0 for no limit:
max-concurrency: 64 max-concurrency: 64
# if true, only check anonymous connections (not logged into an account)
# at the very end of the handshake:
exempt-sasl: false
# IP cloaking hides users' IP addresses from other users and from channel admins # IP cloaking hides users' IP addresses from other users and from channel admins
# (but not from server admins), while still allowing channel admins to ban # (but not from server admins), while still allowing channel admins to ban

View File

@ -84,7 +84,7 @@ type IPScriptOutput struct {
Error string `json:"error"` Error string `json:"error"`
} }
func CheckIPBan(sem utils.Semaphore, config ScriptConfig, addr net.IP) (output IPScriptOutput, err error) { func CheckIPBan(sem utils.Semaphore, config IPCheckScriptConfig, addr net.IP) (output IPScriptOutput, err error) {
if sem != nil { if sem != nil {
sem.Acquire() sem.Acquire()
defer sem.Release() defer sem.Release()

View File

@ -348,6 +348,11 @@ type AuthScriptConfig struct {
Autocreate bool Autocreate bool
} }
type IPCheckScriptConfig struct {
ScriptConfig `yaml:",inline"`
ExemptSASL bool `yaml:"exempt-sasl"`
}
// AccountRegistrationConfig controls account registration. // AccountRegistrationConfig controls account registration.
type AccountRegistrationConfig struct { type AccountRegistrationConfig struct {
Enabled bool Enabled bool
@ -587,12 +592,12 @@ type Config struct {
supportedCapsWithoutSTS *caps.Set supportedCapsWithoutSTS *caps.Set
capValues caps.Values capValues caps.Values
Casemapping Casemapping Casemapping Casemapping
EnforceUtf8 bool `yaml:"enforce-utf8"` EnforceUtf8 bool `yaml:"enforce-utf8"`
OutputPath string `yaml:"output-path"` OutputPath string `yaml:"output-path"`
IPCheckScript ScriptConfig `yaml:"ip-check-script"` IPCheckScript IPCheckScriptConfig `yaml:"ip-check-script"`
OverrideServicesHostname string `yaml:"override-services-hostname"` OverrideServicesHostname string `yaml:"override-services-hostname"`
MaxLineLen int `yaml:"max-line-len"` MaxLineLen int `yaml:"max-line-len"`
SuppressLusers bool `yaml:"suppress-lusers"` SuppressLusers bool `yaml:"suppress-lusers"`
} }
Roleplay struct { Roleplay struct {

View File

@ -200,7 +200,7 @@ func (server *Server) checkBans(config *Config, ipaddr net.IP, checkScripts bool
server.logger.Warning("internal", "unexpected ban result", err.Error()) server.logger.Warning("internal", "unexpected ban result", err.Error())
} }
if checkScripts && config.Server.IPCheckScript.Enabled { if checkScripts && config.Server.IPCheckScript.Enabled && !config.Server.IPCheckScript.ExemptSASL {
output, err := CheckIPBan(server.semaphores.IPCheckScript, config.Server.IPCheckScript, ipaddr) output, err := CheckIPBan(server.semaphores.IPCheckScript, config.Server.IPCheckScript, ipaddr)
if err != nil { if err != nil {
server.logger.Error("internal", "couldn't check IP ban script", ipaddr.String(), err.Error()) server.logger.Error("internal", "couldn't check IP ban script", ipaddr.String(), err.Error())
@ -267,9 +267,26 @@ func (server *Server) handleAlwaysOnExpirations() {
} }
} }
// // handles server.ip-check-script.exempt-sasl:
// server functionality // run the ip check script at the end of the handshake, only for anonymous connections
// func (server *Server) checkBanScriptExemptSASL(config *Config, session *Session) (outcome AuthOutcome) {
// TODO add caching for this; see related code in (*server).checkBans;
// we should probably just put an LRU around this instead of using the DLINE system
ipaddr := session.IP()
output, err := CheckIPBan(server.semaphores.IPCheckScript, config.Server.IPCheckScript, ipaddr)
if err != nil {
server.logger.Error("internal", "couldn't check IP ban script", ipaddr.String(), err.Error())
return authSuccess
}
if output.Result == IPBanned || output.Result == IPRequireSASL {
server.logger.Info("connect-ip", "Rejecting unauthenticated client due to ip-check-script", ipaddr.String())
if output.BanMessage != "" {
session.client.requireSASLMessage = output.BanMessage
}
return authFailSaslRequired
}
return authSuccess
}
func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) { func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
// XXX PROXY or WEBIRC MUST be sent as the first line of the session; // XXX PROXY or WEBIRC MUST be sent as the first line of the session;
@ -294,6 +311,10 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
// before completing the other registration commands // before completing the other registration commands
config := server.Config() config := server.Config()
authOutcome := c.isAuthorized(server, config, session, c.requireSASL) authOutcome := c.isAuthorized(server, config, session, c.requireSASL)
if authOutcome == authSuccess && c.account == "" &&
config.Server.IPCheckScript.Enabled && config.Server.IPCheckScript.ExemptSASL {
authOutcome = server.checkBanScriptExemptSASL(config, session)
}
var quitMessage string var quitMessage string
switch authOutcome { switch authOutcome {
case authFailPass: case authFailPass:

View File

@ -274,6 +274,9 @@ server:
kill-timeout: 1s kill-timeout: 1s
# how many scripts are allowed to run at once? 0 for no limit: # how many scripts are allowed to run at once? 0 for no limit:
max-concurrency: 64 max-concurrency: 64
# if true, only check anonymous connections (not logged into an account)
# at the very end of the handshake:
exempt-sasl: false
# IP cloaking hides users' IP addresses from other users and from channel admins # IP cloaking hides users' IP addresses from other users and from channel admins
# (but not from server admins), while still allowing channel admins to ban # (but not from server admins), while still allowing channel admins to ban