Browse Source

Added IsBanned checking API

tobychui 3 years ago
parent
commit
d15058ade9
3 changed files with 101 additions and 21 deletions
  1. 90 20
      mod/auth/blacklist/blacklist.go
  2. 11 0
      mod/auth/blacklist/blacklist_test.go
  3. 0 1
      web/desktop.system

+ 90 - 20
mod/auth/blacklist/blacklist.go

@@ -1,6 +1,7 @@
 package blacklist
 
 import (
+	"bytes"
 	"errors"
 	"net"
 	"strconv"
@@ -41,9 +42,30 @@ func (bl *BlackList) IsBanned(ip string) bool {
 	if bl.database.KeyExists("ipblacklist", ip) {
 		return true
 	}
+
+	//The ip might be inside as a range. Do a range search.
+	//Need optimization, current implementation is O(N)
+	for _, thisIpRange := range bl.ListBannedIpRanges() {
+		if ipInRange(ip, thisIpRange) {
+			return true
+		}
+	}
 	return false
 }
 
+func (bl *BlackList) ListBannedIpRanges() []string {
+	entries, err := bl.database.ListTable("test")
+	if err != nil {
+		panic(err)
+	}
+	results := []string{}
+	for _, keypairs := range entries {
+		thisIpRange := keypairs[0]
+		results = append(results, string(thisIpRange))
+	}
+	return results
+}
+
 //Set the ban state of a ip or ip range
 func (bl *BlackList) Ban(ipRange string) error {
 	//Check if the IP range is correct
@@ -58,16 +80,65 @@ func (bl *BlackList) Ban(ipRange string) error {
 	return bl.database.Write("ipblacklist", ipRange, true)
 }
 
+//Unban an IP or IP range
 func (bl *BlackList) UnBan(ipRange string) error {
 	//Check if the IP range is correct
-	return nil
+	err := validateIpRange(ipRange)
+	if err != nil {
+		return err
+	}
+
+	//Check if the ip range is banned
+	if !bl.database.KeyExists("ipblacklist", ipRange) {
+		return errors.New("invalid IP range given")
+	}
 
+	//Ip range exists, remove it from database
+	return bl.database.Delete("ipblacklist", ipRange)
+}
+
+//Break an ip range text into independent ip strings
+func breakdownIpRange(ipRange string) []string {
+	ipRange = strings.ReplaceAll(ipRange, " ", "")
+	err := validateIpRange(ipRange)
+	if err != nil {
+		return []string{}
+	}
+	if !strings.Contains(ipRange, "-") {
+		//This is not an ip range but a single ip
+		return []string{ipRange}
+	}
+
+	//Break down the IP range
+	results := []string{}
+	ips := strings.Split(ipRange, "-")
+
+	subnet := ips[0][:strings.LastIndex(ips[0], ".")]
+	startD := ips[0][strings.LastIndex(ips[0], ".")+1:]
+	if err != nil {
+		return []string{}
+	}
+	endD := ips[1][strings.LastIndex(ips[0], ".")+1:]
+	if err != nil {
+		return []string{}
+	}
+
+	startDInt, err := strconv.Atoi(startD)
+	endDInt, err := strconv.Atoi(endD)
+
+	currentDInt := startDInt
+	for currentDInt < endDInt+1 {
+		results = append(results, subnet+"."+strconv.Itoa(currentDInt))
+		currentDInt++
+	}
+
+	return results
 }
 
 //Check if an given ip in the given range
 func ipInRange(ip string, ipRange string) bool {
 	ip = strings.TrimSpace(ip)
-	ipRange = strings.TrimSpace(ipRange)
+	ipRange = strings.ReplaceAll(ipRange, " ", "")
 	if ip == ipRange {
 		//For fields that the ipRange is the ip itself
 		return true
@@ -75,27 +146,26 @@ func ipInRange(ip string, ipRange string) bool {
 
 	//Try matching range
 	if strings.Contains(ipRange, "-") {
-		//For range, in A.B.C.D, the A.B.C part must be the same, so do prefix matching
+		//Parse the source IP
+		trial := net.ParseIP(ip)
+
+		//Parse the IP range
 		ips := strings.Split(ipRange, "-")
-		startSubnet := ips[0][:strings.LastIndex(ips[0], ".")]
-		targetIpSubnet := ip[:strings.LastIndex(ip, ".")]
-		if startSubnet == targetIpSubnet {
-			//Check the last value in range
-			StartDval, _ := strconv.Atoi(ips[0][strings.LastIndex(ips[0], ".")+1:])
-			EndDval, _ := strconv.Atoi(ips[1][strings.LastIndex(ips[1], ".")+1:])
-			thisDVal, _ := strconv.Atoi(ip[strings.LastIndex(ip, ".")+1:])
-
-			if thisDVal > StartDval && thisDVal < EndDval {
-				//In range
-				return true
-			} else {
-				//Not in range
-				return false
-			}
-		} else {
-			//Subnet different. Must be not in this range
+		ip1 := net.ParseIP(ips[0])
+		if ip1 == nil {
+			return false
+		}
+		ip2 := net.ParseIP(ips[1])
+		if ip2 == nil {
+			return false
+		}
+		if trial.To4() == nil {
 			return false
 		}
+		if bytes.Compare(trial, ip1) >= 0 && bytes.Compare(trial, ip2) <= 0 {
+			return true
+		}
+		return false
 
 	}
 	return false

+ 11 - 0
mod/auth/blacklist/blacklist_test.go

@@ -4,6 +4,17 @@ import (
 	"testing"
 )
 
+func TestIpRangeBreakdown(t *testing.T) {
+	ipRange := "192.168.1.155 - 192.168.1.158"
+	sol := []string{"192.168.1.155", "192.168.1.156", "192.168.1.157", "192.168.1.158"}
+	breakdown := breakdownIpRange(ipRange)
+	if len(sol) != len(breakdown) {
+		t.Fatal("IP range breakdown length incorrect, result: ", breakdown)
+	} else {
+		t.Log("Returned IP Range: ", breakdown, " Solution: ", sol)
+	}
+}
+
 func TestIpInRange(t *testing.T) {
 	r := ipInRange("192.168.1.128", "192.168.1.100 - 192.168.1.200")
 	if r == false {

+ 0 - 1
web/desktop.system

@@ -2118,7 +2118,6 @@
                     $(object).find(".maxToogleButton").attr('src', "img/system/restore.png");
                 }
             }
-
         }
 
         //Handle floatWindow min, max and close