2019-10-07 18:21:26 +05:00
package httpserver
import (
"net"
"net/http"
"strings"
2021-11-20 23:06:40 +05:00
"github.com/labstack/echo"
2019-10-13 15:12:54 +05:00
"go.dev.pztrn.name/giredore/internal/configuration"
"go.dev.pztrn.name/giredore/internal/structs"
2019-10-07 18:21:26 +05:00
)
func checkAllowedIPs ( ) echo . MiddlewareFunc {
return func ( next echo . HandlerFunc ) echo . HandlerFunc {
2021-11-20 23:06:40 +05:00
return func ( ectx echo . Context ) error {
2019-10-07 18:21:26 +05:00
// Do nothing if request came not in "/_api" namespace.
2021-11-20 23:06:40 +05:00
if ! strings . HasPrefix ( ectx . Request ( ) . RequestURI , "/_api" ) {
return next ( ectx )
2019-10-07 18:21:26 +05:00
}
// Get IPs and subnets from configuration and parse them
// into comparable things.
// If IP address was specified without network mask - assume /32.
var subnets [ ] * net . IPNet
2020-04-25 13:47:19 +05:00
2019-10-07 18:21:26 +05:00
allowedIPs := configuration . Cfg . GetAllowedIPs ( )
2020-04-25 13:47:19 +05:00
2019-10-07 18:21:26 +05:00
for _ , ip := range allowedIPs {
ipToParse := ip
if ! strings . Contains ( ip , "/" ) {
ipToParse = ip + "/32"
}
_ , net , err := net . ParseCIDR ( ipToParse )
if err != nil {
log . Error ( ) . Err ( err ) . Str ( "subnet" , ipToParse ) . Msg ( "Failed to parse CIDR. /_api/ endpoint won't be accessible, this should be fixed manually in configuration file!" )
2021-11-20 23:06:40 +05:00
// nolint:exhaustivestruct,wrapcheck
return ectx . JSON ( http . StatusInternalServerError , & structs . Reply { Status : structs . StatusFailure , Errors : [ ] structs . Error { structs . ErrInvalidAllowedIPDefined } } )
2019-10-07 18:21:26 +05:00
}
subnets = append ( subnets , net )
}
// Check if requester's IP address are within allowed IP
// subnets.
2021-11-20 23:06:40 +05:00
ipToCheck := net . ParseIP ( ectx . RealIP ( ) )
2020-04-25 13:47:19 +05:00
2019-10-07 18:21:26 +05:00
var allowed bool
2020-04-25 13:47:19 +05:00
2019-10-07 18:21:26 +05:00
for _ , subnet := range subnets {
if subnet . Contains ( ipToCheck ) {
allowed = true
2021-11-20 23:06:40 +05:00
2019-10-07 18:21:26 +05:00
break
}
}
if allowed {
2021-11-20 23:06:40 +05:00
return next ( ectx )
2019-10-07 18:21:26 +05:00
}
2021-11-20 23:06:40 +05:00
// nolint:exhaustivestruct,wrapcheck
return ectx . JSON ( http . StatusBadRequest , & structs . Reply { Status : structs . StatusFailure , Errors : [ ] structs . Error { structs . ErrIPAddressNotAllowed } } )
2019-10-07 18:21:26 +05:00
}
}
}