2021-03-05 11:18:31 +07:00
|
|
|
package authorization
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-04-01 18:38:49 +07:00
|
|
|
"regexp"
|
2021-03-05 11:18:31 +07:00
|
|
|
"strings"
|
|
|
|
|
2021-08-11 08:04:35 +07:00
|
|
|
"github.com/authelia/authelia/v4/internal/utils"
|
2021-03-05 11:18:31 +07:00
|
|
|
)
|
|
|
|
|
2022-04-01 18:38:49 +07:00
|
|
|
// NewAccessControlDomain creates a new SubjectObjectMatcher that matches the domain as a basic string.
|
2022-06-28 09:51:05 +07:00
|
|
|
func NewAccessControlDomain(domain string) AccessControlDomain {
|
|
|
|
m := &AccessControlDomainMatcher{}
|
2022-04-01 18:38:49 +07:00
|
|
|
domain = strings.ToLower(domain)
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(domain, "*."):
|
2022-06-28 09:51:05 +07:00
|
|
|
m.Wildcard = true
|
|
|
|
m.Name = domain[1:]
|
2022-04-01 18:38:49 +07:00
|
|
|
case strings.HasPrefix(domain, "{user}"):
|
2022-06-28 09:51:05 +07:00
|
|
|
m.UserWildcard = true
|
|
|
|
m.Name = domain[7:]
|
2022-04-01 18:38:49 +07:00
|
|
|
case strings.HasPrefix(domain, "{group}"):
|
2022-06-28 09:51:05 +07:00
|
|
|
m.GroupWildcard = true
|
|
|
|
m.Name = domain[8:]
|
2021-03-05 11:18:31 +07:00
|
|
|
default:
|
2022-06-28 09:51:05 +07:00
|
|
|
m.Name = domain
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
|
|
|
|
2022-06-28 09:51:05 +07:00
|
|
|
return AccessControlDomain{m}
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewAccessControlDomainRegex creates a new SubjectObjectMatcher that matches the domain either in a basic way or
|
|
|
|
// dynamic User/Group subexpression group way.
|
2022-06-28 09:51:05 +07:00
|
|
|
func NewAccessControlDomainRegex(pattern regexp.Regexp) AccessControlDomain {
|
2022-04-01 18:38:49 +07:00
|
|
|
var iuser, igroup = -1, -1
|
|
|
|
|
|
|
|
for i, group := range pattern.SubexpNames() {
|
|
|
|
switch group {
|
|
|
|
case subexpNameUser:
|
|
|
|
iuser = i
|
|
|
|
case subexpNameGroup:
|
|
|
|
igroup = i
|
|
|
|
}
|
2021-03-05 11:18:31 +07:00
|
|
|
}
|
2022-04-01 18:38:49 +07:00
|
|
|
|
|
|
|
if iuser != -1 || igroup != -1 {
|
2022-06-28 09:51:05 +07:00
|
|
|
return AccessControlDomain{RegexpGroupStringSubjectMatcher{pattern, iuser, igroup}}
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
|
|
|
|
2022-06-28 09:51:05 +07:00
|
|
|
return AccessControlDomain{RegexpStringSubjectMatcher{pattern}}
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
|
|
|
|
2022-06-28 09:51:05 +07:00
|
|
|
// AccessControlDomainMatcher is the basic domain matcher.
|
|
|
|
type AccessControlDomainMatcher struct {
|
|
|
|
Name string
|
|
|
|
Wildcard bool
|
|
|
|
UserWildcard bool
|
|
|
|
GroupWildcard bool
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
|
|
|
|
2022-06-28 09:51:05 +07:00
|
|
|
// IsMatch returns true if this rule matches.
|
|
|
|
func (m AccessControlDomainMatcher) IsMatch(domain string, subject Subject) (match bool) {
|
|
|
|
switch {
|
|
|
|
case m.Wildcard:
|
|
|
|
return strings.HasSuffix(domain, m.Name)
|
|
|
|
case m.UserWildcard:
|
|
|
|
return domain == fmt.Sprintf("%s.%s", subject.Username, m.Name)
|
|
|
|
case m.GroupWildcard:
|
|
|
|
prefix, suffix := domainToPrefixSuffix(domain)
|
|
|
|
|
|
|
|
return suffix == m.Name && utils.IsStringInSliceFold(prefix, subject.Groups)
|
|
|
|
default:
|
|
|
|
return strings.EqualFold(domain, m.Name)
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
2022-06-28 09:51:05 +07:00
|
|
|
}
|
2022-04-01 18:38:49 +07:00
|
|
|
|
2022-06-28 09:51:05 +07:00
|
|
|
// AccessControlDomain represents an ACL domain.
|
|
|
|
type AccessControlDomain struct {
|
|
|
|
Matcher StringSubjectMatcher
|
2022-04-01 18:38:49 +07:00
|
|
|
}
|
|
|
|
|
2022-06-28 09:51:05 +07:00
|
|
|
// IsMatch returns true if the ACL domain matches the object domain.
|
|
|
|
func (acl AccessControlDomain) IsMatch(subject Subject, object Object) (match bool) {
|
|
|
|
return acl.Matcher.IsMatch(object.Domain, subject)
|
2021-03-05 11:18:31 +07:00
|
|
|
}
|