Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/netip"
"os"
"reflect"
"regexp"
"slices"
"strconv"
"strings"
Expand Down Expand Up @@ -45,6 +44,7 @@ import (
"github.com/netbirdio/netbird/management/server/types"
"github.com/netbirdio/netbird/management/server/util"
"github.com/netbirdio/netbird/route"
"github.com/netbirdio/netbird/shared/management/domain"
"github.com/netbirdio/netbird/shared/management/status"
)

Expand Down Expand Up @@ -224,7 +224,7 @@ func BuildManager(
// enable single account mode only if configured by user and number of existing accounts is not grater than 1
am.singleAccountMode = singleAccountModeDomain != "" && accountsCounter <= 1
if am.singleAccountMode {
if !isDomainValid(singleAccountModeDomain) {
if !domain.IsValidDomain(singleAccountModeDomain) {
return nil, status.Errorf(status.InvalidArgument, "invalid domain \"%s\" provided for a single account mode. Please review your input for --single-account-mode-domain", singleAccountModeDomain)
}
am.singleAccountModeDomain = singleAccountModeDomain
Expand Down Expand Up @@ -401,7 +401,7 @@ func (am *DefaultAccountManager) validateSettingsUpdate(ctx context.Context, tra
return status.Errorf(status.InvalidArgument, "peer login expiration can't be smaller than one hour")
}

if newSettings.DNSDomain != "" && !isDomainValid(newSettings.DNSDomain) {
if newSettings.DNSDomain != "" && !domain.IsValidDomain(newSettings.DNSDomain) {
return status.Errorf(status.InvalidArgument, "invalid domain \"%s\" provided for DNS domain", newSettings.DNSDomain)
}

Expand Down Expand Up @@ -1518,7 +1518,7 @@ func (am *DefaultAccountManager) getAccountIDWithAuthorizationClaims(ctx context
return userAuth.AccountId, nil
}

if userAuth.DomainCategory != types.PrivateCategory || !isDomainValid(userAuth.Domain) {
if userAuth.DomainCategory != types.PrivateCategory || !domain.IsValidDomain(userAuth.Domain) {
return am.GetAccountIDByUserID(ctx, userAuth.UserId, userAuth.Domain)
}

Expand Down Expand Up @@ -1701,12 +1701,6 @@ func (am *DefaultAccountManager) HasConnectedChannel(peerID string) bool {
return am.peersUpdateManager.HasChannel(peerID)
}

var invalidDomainRegexp = regexp.MustCompile(`^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$`)

func isDomainValid(domain string) bool {
return invalidDomainRegexp.MatchString(domain)
}

// GetDNSDomain returns the configured dnsDomain
func (am *DefaultAccountManager) GetDNSDomain(settings *types.Settings) string {
if settings == nil {
Expand Down
27 changes: 3 additions & 24 deletions management/server/nameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ package server

import (
"context"
"errors"
"regexp"
"unicode/utf8"

"github.com/miekg/dns"
"github.com/rs/xid"

nbdns "github.com/netbirdio/netbird/dns"
Expand All @@ -15,13 +12,10 @@ import (
"github.com/netbirdio/netbird/management/server/permissions/operations"
"github.com/netbirdio/netbird/management/server/store"
"github.com/netbirdio/netbird/management/server/types"
nbDomain "github.com/netbirdio/netbird/shared/management/domain"
"github.com/netbirdio/netbird/shared/management/status"
)

const domainPattern = `^(?i)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*[*.a-z]{1,}$`

var invalidDomainName = errors.New("invalid domain name")

// GetNameServerGroup gets a nameserver group object from account and nameserver group IDs
func (am *DefaultAccountManager) GetNameServerGroup(ctx context.Context, accountID, userID, nsGroupID string) (*nbdns.NameServerGroup, error) {
allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Read)
Expand Down Expand Up @@ -268,8 +262,8 @@ func validateDomainInput(primary bool, domains []string, searchDomainsEnabled bo
}

for _, domain := range domains {
if err := validateDomain(domain); err != nil {
return status.Errorf(status.InvalidArgument, "nameserver group got an invalid domain: %s %q", domain, err)
if nbDomain.IsValidDomain(domain) {
return status.Errorf(status.InvalidArgument, "nameserver group got an invalid domain: %s", domain)
}
}
return nil
Expand Down Expand Up @@ -313,18 +307,3 @@ func validateGroups(list []string, groups map[string]*types.Group) error {

return nil
}

var domainMatcher = regexp.MustCompile(domainPattern)

func validateDomain(domain string) error {
if !domainMatcher.MatchString(domain) {
return errors.New("domain should consists of only letters, numbers, and hyphens with no leading, trailing hyphens, or spaces")
}

_, valid := dns.IsDomainName(domain)
if !valid {
return invalidDomainName
}

return nil
}
8 changes: 3 additions & 5 deletions management/server/networks/resources/types/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import (
"errors"
"fmt"
"net/netip"
"regexp"

"github.com/rs/xid"

nbDomain "github.com/netbirdio/netbird/shared/management/domain"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/route"
nbDomain "github.com/netbirdio/netbird/shared/management/domain"

"github.com/netbirdio/netbird/shared/management/http/api"
)
Expand Down Expand Up @@ -166,9 +165,8 @@ func GetResourceType(address string) (NetworkResourceType, string, netip.Prefix,
return Host, "", netip.PrefixFrom(ip, ip.BitLen()), nil
}

domainRegex := regexp.MustCompile(`^(\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$`)
if domainRegex.MatchString(address) {
return Domain, address, netip.Prefix{}, nil
if domain, err := nbDomain.ToValidDomain(address); err == nil {
return Domain, string(domain), netip.Prefix{}, nil
}

return "", "", netip.Prefix{}, errors.New("not a valid host, subnet, or domain")
Expand Down
38 changes: 29 additions & 9 deletions shared/management/domain/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,11 @@ func ValidateDomains(domains []string) (List, error) {
var domainList List

for _, d := range domains {
// handles length and idna conversion
punycode, err := FromString(d)
validDomain, err := ToValidDomain(d)
if err != nil {
return domainList, fmt.Errorf("convert domain to punycode: %s: %w", d, err)
return nil, fmt.Errorf("invalid domain %s: %w", d, err)
}

if !domainRegex.MatchString(string(punycode)) {
return domainList, fmt.Errorf("invalid domain format: %s", d)
}

domainList = append(domainList, punycode)
domainList = append(domainList, validDomain)
}
return domainList, nil
}
Expand All @@ -54,3 +48,29 @@ func ValidateDomainsList(domains []string) error {
}
return nil
}

// IsValidDomain checks if the given domain is valid.
func IsValidDomain(domain string) bool {
// handles length and idna conversion
punycode, err := FromString(domain)
if err != nil {
return false
}

return !domainRegex.MatchString(string(punycode))
}

// ToValidDomain converts a domain to a valid domain format.
func ToValidDomain(domain string) (Domain, error) {
// handles length and idna conversion
punycode, err := FromString(domain)
if err != nil {
return "", fmt.Errorf("convert domain to punycode: %s: %w", domain, err)
}

if !domainRegex.MatchString(string(punycode)) {
return "", fmt.Errorf("invalid domain format: %s", domain)
}

return punycode, nil
}
Loading