mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-28 06:49:24 +01:00
143 lines
3.7 KiB
Go
143 lines
3.7 KiB
Go
|
package irc
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/oragono/oragono/irc/sno"
|
||
|
)
|
||
|
|
||
|
func ReverseAddress(ip net.IP) string {
|
||
|
// This is a IPv4 address
|
||
|
if ip.To4() != nil {
|
||
|
address := strings.Split(ip.String(), ".")
|
||
|
|
||
|
for i, j := 0, len(address)-1; i < j; i, j = i+1, j-1 {
|
||
|
address[i], address[j] = address[j], address[i]
|
||
|
}
|
||
|
|
||
|
return strings.Join(address, ".")
|
||
|
}
|
||
|
|
||
|
// fallback to returning the String of IP if it is not an IPv4 address
|
||
|
return ip.String()
|
||
|
}
|
||
|
|
||
|
func LastIpOctet(addr string) string {
|
||
|
address := strings.Split(addr, ".")
|
||
|
|
||
|
return address[len(address)-1]
|
||
|
}
|
||
|
|
||
|
func (server *Server) LookupBlacklistEntry(list *DnsblListEntry, client *Client) []string {
|
||
|
res, err := net.LookupHost(fmt.Sprintf("%s.%s", ReverseAddress(client.IP()), list.Host))
|
||
|
|
||
|
var entries []string
|
||
|
if err != nil {
|
||
|
server.logger.Info("dnsbl-lookup", fmt.Sprintf("DNSBL loopup failed: %s", err))
|
||
|
return entries
|
||
|
}
|
||
|
|
||
|
if len(res) > 0 {
|
||
|
for _, addr := range res {
|
||
|
entries = append(entries, LastIpOctet(addr))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return entries
|
||
|
}
|
||
|
|
||
|
func sendDnsblMessage(client *Client, message string) {
|
||
|
/*fmt.Printf(client.server.DnsblConfig().Channel)
|
||
|
if channel := client.server.DnsblConfig().Channel; channel != "" {
|
||
|
fmt.Printf(channel)
|
||
|
client.Send(nil, client.server.name, "PRIVMSG", channel, message)
|
||
|
}
|
||
|
*/
|
||
|
client.server.snomasks.Send(sno.Dnsbl, message)
|
||
|
}
|
||
|
|
||
|
// ProcessBlacklist does
|
||
|
func (server *Server) ProcessBlacklist(client *Client) {
|
||
|
|
||
|
if !server.DnsblConfig().Enabled || len(server.DnsblConfig().Lists) == 0 {
|
||
|
// do nothing if dnsbl is disabled, empty lists is treated as if dnsbl was disabled
|
||
|
return
|
||
|
}
|
||
|
|
||
|
type DnsblTypeResponse struct {
|
||
|
Host string
|
||
|
Action string
|
||
|
Reason string
|
||
|
}
|
||
|
var items = []DnsblTypeResponse{}
|
||
|
for _, list := range server.DnsblConfig().Lists {
|
||
|
response := DnsblTypeResponse{
|
||
|
Host: list.Host,
|
||
|
Action: list.Action,
|
||
|
Reason: list.Reason,
|
||
|
}
|
||
|
// update action/reason if matched with new ...
|
||
|
for _, entry := range server.LookupBlacklistEntry(&list, client) {
|
||
|
if reply, exists := list.Reply[entry]; exists {
|
||
|
response.Action, response.Reason = reply.Action, reply.Reason
|
||
|
}
|
||
|
items = append(items, response)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Sort responses so that require-sasl blocks come first. Otherwise A>B (allow>block, allow>notify, block>notify)
|
||
|
// so that responses come in this order:
|
||
|
// - require-sasl
|
||
|
// - allow
|
||
|
// - block
|
||
|
// - notify
|
||
|
sort.Slice(items, func(i, j int) bool {
|
||
|
if items[i].Action == "require-sasl" {
|
||
|
return true
|
||
|
}
|
||
|
return items[i].Action > items[j].Action
|
||
|
})
|
||
|
|
||
|
if len(items) > 0 {
|
||
|
item := items[0]
|
||
|
switch item.Action {
|
||
|
case "require-sasl":
|
||
|
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s matched %s, requiring SASL to proceed", client.IP(), item.Host))
|
||
|
client.SetRequireSasl(true, item.Reason)
|
||
|
|
||
|
case "block":
|
||
|
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s matched %s - killing", client.IP(), item.Host))
|
||
|
client.Quit(strings.Replace(item.Reason, "{ip}", client.IPString(), -1))
|
||
|
|
||
|
case "notify":
|
||
|
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s matched %s", client.IP(), item.Host))
|
||
|
|
||
|
case "allow":
|
||
|
sendDnsblMessage(client, fmt.Sprintf("Allowing host %s [%s]", client.IP(), item.Host))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func connectionRequiresSasl(client *Client) bool {
|
||
|
sasl, reason := client.RequireSasl()
|
||
|
|
||
|
if !sasl {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if client.Account() == "" {
|
||
|
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s and did not authenticate through SASL - blocking connection", client.IP()))
|
||
|
client.Quit(strings.Replace(reason, "{ip}", client.IPString(), -1))
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s authenticated through SASL - allowing", client.IP()))
|
||
|
|
||
|
return false
|
||
|
}
|