authelia/internal/authorization/ip_matcher.go
Amir Zarrinkafsh 9ca0e940da
[FEATURE] Validate ACLs and add network groups (#1568)
* adds validation to ACL's
* adds a new networks section that can be used as aliases in other sections (currently access_control)
2021-01-04 21:55:23 +11:00

76 lines
1.7 KiB
Go

package authorization
import (
"net"
"strings"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/logging"
)
func selectMatchingNetworkGroups(networks []string, aclNetworks []schema.ACLNetwork) []schema.ACLNetwork {
selectedNetworkGroups := []schema.ACLNetwork{}
for _, network := range networks {
for _, n := range aclNetworks {
for _, ng := range n.Name {
if network == ng {
selectedNetworkGroups = append(selectedNetworkGroups, n)
}
}
}
}
return selectedNetworkGroups
}
func isIPAddressOrCIDR(ip net.IP, network string) bool {
switch {
case ip.String() == network:
return true
case strings.Contains(network, "/"):
return parseCIDR(ip, network)
}
return false
}
func parseCIDR(ip net.IP, network string) bool {
_, ipNet, err := net.ParseCIDR(network)
if err != nil {
logging.Logger().Errorf("Failed to parse network %s: %s", network, err)
}
if ipNet.Contains(ip) {
return true
}
return false
}
// isIPMatching check whether user's IP is in one of the network ranges.
func isIPMatching(ip net.IP, networks []string, aclNetworks []schema.ACLNetwork) bool {
// If no network is provided in the rule, we match any network
if len(networks) == 0 {
return true
}
matchingNetworkGroups := selectMatchingNetworkGroups(networks, aclNetworks)
for _, network := range networks {
if net.ParseIP(network) == nil && !strings.Contains(network, "/") {
for _, n := range matchingNetworkGroups {
for _, network := range n.Networks {
if isIPAddressOrCIDR(ip, network) {
return true
}
}
}
} else if isIPAddressOrCIDR(ip, network) {
return true
}
}
return false
}