From e52ffaf686c019f3d7eba5697d1de9db832a9830 Mon Sep 17 00:00:00 2001 From: Khanh Ngo Date: Wed, 22 Apr 2020 00:08:48 +0700 Subject: [PATCH] Validate the client IP allocation --- handler/routes.go | 28 ++++++++++++++++++---------- util/util.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/handler/routes.go b/handler/routes.go index f27e441..b103c08 100644 --- a/handler/routes.go +++ b/handler/routes.go @@ -89,11 +89,25 @@ func NewClient() echo.HandlerFunc { client := new(model.Client) c.Bind(client) + // initialize db + dir := "./db" + db, err := scribble.New(dir, nil) + if err != nil { + log.Error("Cannot initialize the database: ", err) + return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot access database"}) + } + + // read server information + serverInterface := model.ServerInterface{} + if err := db.Read("server", "interfaces", &serverInterface); err != nil { + log.Error("Cannot fetch server interface config from database: ", err) + } + // validate the input Allocation IPs - // TODO: validate if they are really available - if util.ValidateCIDRList(client.AllocatedIPs) == false { - log.Warnf("Invalid allocation ip input from user: %v", client.AllocatedIPs) - return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "IP allocation is not valid"}) + allocatedIPs, err := util.GetAllocatedIPs() + check, err := util.ValidateIPAllocation(serverInterface.Addresses, allocatedIPs, client.AllocatedIPs) + if !check { + return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, fmt.Sprintf("%s", err)}) } // validate the input AllowedIPs @@ -118,12 +132,6 @@ func NewClient() echo.HandlerFunc { client.UpdatedAt = client.CreatedAt // write client to the database - dir := "./db" - db, err := scribble.New(dir, nil) - if err != nil { - log.Error("Cannot initialize the database: ", err) - return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot access database"}) - } db.Write("clients", client.ID, client) log.Infof("Created wireguard client: %v", client) diff --git a/util/util.go b/util/util.go index c355f42..e57d3bc 100644 --- a/util/util.go +++ b/util/util.go @@ -268,3 +268,43 @@ func GetAvailableIP(cidr string, allocatedList []string) (string, error) { return "", errors.New("No more available ip address") } + +// ValidateIPAllocation to validate the list of client's ip allocation +// They must have a correct format and available in serverAddresses space +func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ipAllocationList []string) (bool, error) { + for _, clientCIDR := range ipAllocationList { + ip, _, _ := net.ParseCIDR(clientCIDR) + + // clientCIDR must be in CIDR format + if ip == nil { + return false, fmt.Errorf("Invalid ip allocation input %s. Must be in CIDR format", clientCIDR) + } + + // return false immediately if the ip is already in use (in ipAllocatedList) + for _, item := range ipAllocatedList { + if item == ip.String() { + return false, fmt.Errorf("IP %s already allocated", ip) + } + } + + // even if it is not in use, we still need to check if it + // belongs to a network of the server. + var isValid bool = false + for _, serverCIDR := range serverAddresses { + _, serverNet, _ := net.ParseCIDR(serverCIDR) + if serverNet.Contains(ip) { + isValid = true + break + } + } + + // current ip allocation is valid, check the next one + if isValid { + continue + } else { + return false, fmt.Errorf("IP %s does not belong to any network addresses of WireGuard server", ip) + } + } + + return true, nil +}