Pull request: 3419 client allowlist collision
Updates #3419.
Squashed commit of the following:
commit 370094c00d9c15b1336fbedb1e233bd4436c9898
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Fri Sep 10 17:31:16 2021 +0300
added link to github issue
commit 407ba9b2db46b887a30ddb081bd37c56e56b0496
Merge: 426c8146 80548233
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Fri Sep 10 17:29:52 2021 +0300
Merge branch 'master' into 3419-client-allowlist-collision
commit 426c8146cff5c112ebb25192af276c6601200528
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Fri Sep 10 16:28:11 2021 +0300
fix en
commit d28c6022321828c6bdc55c3f9a4f655b26d146d2
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Fri Sep 10 15:49:12 2021 +0300
added missing space
commit b374a09327968ca5343c1595d1ab8cf317c15ffe
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Fri Sep 10 15:43:55 2021 +0300
fixes after review
commit 2be629d66e4703e2f5a85615bf1eaaa92e03c6fd
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Thu Sep 9 14:17:19 2021 +0300
fixes
commit 5c2aa6201cc0ecf404d4057e354fbb0bdadcdd6d
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Wed Sep 8 15:04:30 2021 +0300
return empty line to locale file
commit 3631c3772babbd595b1c3de4a7e91be6bac3e80f
Author: Dmitriy Seregin <d.seregin@adguard.com>
Date: Wed Sep 8 13:57:51 2021 +0300
all: fix collisions in access lists && expand block/unblock client
This commit is contained in:
committed by
Ainar Garipov
parent
80548233ba
commit
8fdd789474
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
@@ -192,6 +193,60 @@ func (s *Server) handleAccessList(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func isUniq(slice []string) (ok bool, uniqueMap map[string]unit) {
|
||||
exists := make(map[string]unit)
|
||||
for _, key := range slice {
|
||||
if _, has := exists[key]; has {
|
||||
return false, nil
|
||||
}
|
||||
exists[key] = unit{}
|
||||
}
|
||||
return true, exists
|
||||
}
|
||||
|
||||
func intersect(mapA, mapB map[string]unit) bool {
|
||||
for key := range mapA {
|
||||
if _, has := mapB[key]; has {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// validateAccessSet checks the internal accessListJSON lists. To search for
|
||||
// duplicates, we cannot compare the new stringutil.Set and []string, because
|
||||
// creating a set for a large array can be an unnecessary algorithmic complexity
|
||||
func validateAccessSet(list accessListJSON) (err error) {
|
||||
const (
|
||||
errAllowedDup errors.Error = "duplicates in allowed clients"
|
||||
errDisallowedDup errors.Error = "duplicates in disallowed clients"
|
||||
errBlockedDup errors.Error = "duplicates in blocked hosts"
|
||||
errIntersect errors.Error = "some items in allowed and " +
|
||||
"disallowed lists at the same time"
|
||||
)
|
||||
|
||||
ok, allowedClients := isUniq(list.AllowedClients)
|
||||
if !ok {
|
||||
return errAllowedDup
|
||||
}
|
||||
|
||||
ok, disallowedClients := isUniq(list.DisallowedClients)
|
||||
if !ok {
|
||||
return errDisallowedDup
|
||||
}
|
||||
|
||||
ok, _ = isUniq(list.BlockedHosts)
|
||||
if !ok {
|
||||
return errBlockedDup
|
||||
}
|
||||
|
||||
if intersect(allowedClients, disallowedClients) {
|
||||
return errIntersect
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
|
||||
list := accessListJSON{}
|
||||
err := json.NewDecoder(r.Body).Decode(&list)
|
||||
@@ -201,6 +256,13 @@ func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = validateAccessSet(list)
|
||||
if err != nil {
|
||||
httpError(r, w, http.StatusBadRequest, err.Error())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var a *accessCtx
|
||||
a, err = newAccessCtx(list.AllowedClients, list.DisallowedClients, list.BlockedHosts)
|
||||
if err != nil {
|
||||
|
||||
@@ -285,39 +285,70 @@ func toQueryLogWHOIS(wi *RuntimeClientWHOISInfo) (cw *querylog.ClientWHOIS) {
|
||||
}
|
||||
}
|
||||
|
||||
// findMultiple is a wrapper around Find to make it a valid client finder for
|
||||
// the query log. err is always nil.
|
||||
// findMultiple returns info about client. If no information about the client
|
||||
// is found, it sends the client by default only with the "Disallowed" field
|
||||
// filled in. err is always nil.
|
||||
func (clients *clientsContainer) findMultiple(ids []string) (c *querylog.Client, err error) {
|
||||
var emptyClient *querylog.Client
|
||||
|
||||
for _, id := range ids {
|
||||
var name string
|
||||
whois := &querylog.ClientWHOIS{}
|
||||
ip := net.ParseIP(id)
|
||||
|
||||
c, ok := clients.Find(id)
|
||||
if ok {
|
||||
name = c.Name
|
||||
} else if ip != nil {
|
||||
var rc *RuntimeClient
|
||||
rc, ok = clients.FindRuntimeClient(ip)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
name = rc.Host
|
||||
whois = toQueryLogWHOIS(rc.WHOISInfo)
|
||||
}
|
||||
|
||||
disallowed, disallowedRule := clients.dnsServer.IsBlockedClient(ip, id)
|
||||
|
||||
return &querylog.Client{
|
||||
Name: name,
|
||||
DisallowedRule: disallowedRule,
|
||||
WHOIS: whois,
|
||||
Disallowed: disallowed,
|
||||
}, nil
|
||||
client := clients.clientInfo(ip, id, disallowed, disallowedRule)
|
||||
|
||||
if client.Name == "" && client.DisallowedRule == "" {
|
||||
emptyClient = client
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
return emptyClient, nil
|
||||
}
|
||||
|
||||
// clientInfo is a wrapper around Find to make it a valid client finder for
|
||||
// the query log.
|
||||
func (clients *clientsContainer) clientInfo(
|
||||
ip net.IP,
|
||||
id string,
|
||||
disallowed bool,
|
||||
rule string,
|
||||
) (c *querylog.Client) {
|
||||
whois := &querylog.ClientWHOIS{}
|
||||
client, ok := clients.Find(id)
|
||||
if ok {
|
||||
return &querylog.Client{
|
||||
Name: client.Name,
|
||||
DisallowedRule: rule,
|
||||
WHOIS: whois,
|
||||
Disallowed: disallowed,
|
||||
}
|
||||
}
|
||||
|
||||
if ip == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var rc *RuntimeClient
|
||||
rc, ok = clients.FindRuntimeClient(ip)
|
||||
if ok {
|
||||
return &querylog.Client{
|
||||
Name: rc.Host,
|
||||
DisallowedRule: rule,
|
||||
WHOIS: toQueryLogWHOIS(rc.WHOISInfo),
|
||||
Disallowed: disallowed,
|
||||
}
|
||||
}
|
||||
|
||||
return &querylog.Client{
|
||||
Name: "",
|
||||
DisallowedRule: rule,
|
||||
WHOIS: &querylog.ClientWHOIS{},
|
||||
Disallowed: disallowed,
|
||||
}
|
||||
}
|
||||
|
||||
func (clients *clientsContainer) Find(id string) (c *Client, ok bool) {
|
||||
|
||||
Reference in New Issue
Block a user