ovpn-admin/validation.go

90 lines
2.2 KiB
Go

package main
import (
"fmt"
"net"
"regexp"
"unicode/utf8"
)
const (
usernameRegexp = `^[a-zA-Z0-9@]+([._]?[a-zA-Z0-9]+)*$`
passwordRegexp = `^[a-zA-Z0-9@$!#%^_\-]+([._]?[a-zA-Z0-9]+)*$`
CCDDescriptionRegexp = `^[a-zA-Z0-9 ]*$`
usernameMinLength = 3
passwordMinLength = 6
)
type (
validator interface {
validateUsername(string) error
validatePassword(string) error
validateCCD(ccd CCD) error
}
validators struct {
reUserName *regexp.Regexp
rePassword *regexp.Regexp
reCCDDescription *regexp.Regexp
}
)
func (v *validators) validateCCD(ccd CCD) error {
if err := v.validateUsername(ccd.User); err != nil {
return err
}
if ccd.ClientAddress != "dynamic" {
if net.ParseIP(ccd.ClientAddress) == nil {
return fmt.Errorf("invalid ClientAddress")
}
}
for _, route := range ccd.CustomRoutes {
if net.ParseIP(route.Address) == nil {
return fmt.Errorf("invalid CustomRoute.Address")
}
if net.ParseIP(route.Mask) == nil {
return fmt.Errorf("invalid CustomRoute.Mask")
}
if utf8.RuneCountInString(route.Description) > 0 && !v.reCCDDescription.MatchString(route.Description) {
return fmt.Errorf("invalid CustomRoute.Description")
}
}
return nil
}
func newValidator() (validator, error) {
reUsername, err := regexp.Compile(usernameRegexp)
if err != nil {
return nil, fmt.Errorf("username regexp compile failed %s", err)
}
rePassword, err := regexp.Compile(passwordRegexp)
if err != nil {
return nil, fmt.Errorf("password regexp compile failed %s", err)
}
reCCDDescription, err := regexp.Compile(CCDDescriptionRegexp)
if err != nil {
return nil, fmt.Errorf("ccd desctiprion regexp compile failed %s", err)
}
return &validators{
reUserName: reUsername,
rePassword: rePassword,
reCCDDescription: reCCDDescription,
}, nil
}
func (v *validators) validateUsername(username string) error {
if usernameMinLength > utf8.RuneCountInString(username) || !v.reUserName.MatchString(username) {
return fmt.Errorf("invalid username")
}
return nil
}
func (v *validators) validatePassword(passwd string) error {
if passwordMinLength > utf8.RuneCountInString(passwd) || !v.rePassword.MatchString(passwd) {
return fmt.Errorf("invalid password")
}
return nil
}