diff --git a/irc/handlers.go b/irc/handlers.go index 17fd905f..bf0ebb79 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -1636,7 +1636,7 @@ func klineHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respon // get comment(s) reason, operReason := getReasonsFromParams(msg.Params, currentArg) - err = server.klines.AddMask(mask, duration, reason, operReason, operName) + err = server.klines.AddMask(mask, duration, false, reason, operReason, operName) if err != nil { rb.Notice(fmt.Sprintf(client.t("Could not successfully save new K-LINE: %s"), err.Error())) return false diff --git a/irc/kline.go b/irc/kline.go index bc1e9123..6cefea02 100644 --- a/irc/kline.go +++ b/irc/kline.go @@ -66,11 +66,12 @@ func (km *KLineManager) AllBans() map[string]IPBanInfo { } // AddMask adds to the blocked list. -func (km *KLineManager) AddMask(mask string, duration time.Duration, reason, operReason, operName string) error { +func (km *KLineManager) AddMask(mask string, duration time.Duration, requireSASL bool, reason, operReason, operName string) error { km.persistenceMutex.Lock() defer km.persistenceMutex.Unlock() info := IPBanInfo{ + RequireSASL: requireSASL, Reason: reason, OperReason: operReason, OperName: operName, @@ -208,13 +209,14 @@ func (km *KLineManager) CheckMasks(masks ...string) (isBanned bool, info IPBanIn for _, entryInfo := range km.entries { for _, mask := range masks { if entryInfo.Matcher.MatchString(mask) { - return true, entryInfo.Info + // apply the most stringent ban (unconditional bans override require-sasl) + if !isBanned || info.RequireSASL { + isBanned, info = true, entryInfo.Info + } } } } - // no matches! - isBanned = false return } diff --git a/irc/server.go b/irc/server.go index ce75ecd8..e2b7bd84 100644 --- a/irc/server.go +++ b/irc/server.go @@ -383,7 +383,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) { // check KLINEs (#671: ignore KLINEs for loopback connections) if !session.IP().IsLoopback() || session.isTor { isBanned, info := server.klines.CheckMasks(c.AllNickmasks()...) - if isBanned { + if isBanned && !(info.RequireSASL && session.client.Account() != "") { c.setKlined() c.Quit(info.BanMessage(c.t("You are banned from this server (%s)")), nil) server.logger.Info("connect", "Client rejected by k-line", c.NickMaskString()) diff --git a/irc/uban.go b/irc/uban.go index 8f0e646a..d69b33e5 100644 --- a/irc/uban.go +++ b/irc/uban.go @@ -163,7 +163,7 @@ func ubanAddHandler(client *Client, target ubanTarget, params []string, rb *Resp case ubanCIDR: err = ubanAddCIDR(client, target, duration, requireSASL, operReason, rb) case ubanNickmask: - err = ubanAddNickmask(client, target, duration, operReason, rb) + err = ubanAddNickmask(client, target, duration, requireSASL, operReason, rb) case ubanNick: err = ubanAddAccount(client, target, duration, operReason, rb) } @@ -242,8 +242,8 @@ func ubanAddCIDR(client *Client, target ubanTarget, duration time.Duration, requ return } -func ubanAddNickmask(client *Client, target ubanTarget, duration time.Duration, operReason string, rb *ResponseBuffer) (err error) { - err = client.server.klines.AddMask(target.nickOrMask, duration, "", operReason, client.Oper().Name) +func ubanAddNickmask(client *Client, target ubanTarget, duration time.Duration, requireSASL bool, operReason string, rb *ResponseBuffer) (err error) { + err = client.server.klines.AddMask(target.nickOrMask, duration, requireSASL, "", operReason, client.Oper().Name) if err == nil { rb.Notice(fmt.Sprintf(client.t("Successfully added UBAN for %s"), target.nickOrMask)) } else {