2021-03-05 04:18:31 +00:00
|
|
|
package authorization
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-04-01 11:38:49 +00:00
|
|
|
"regexp"
|
2021-03-05 04:18:31 +00:00
|
|
|
"strings"
|
|
|
|
|
2021-08-11 01:04:35 +00:00
|
|
|
"github.com/authelia/authelia/v4/internal/utils"
|
2021-03-05 04:18:31 +00:00
|
|
|
)
|
|
|
|
|
2022-04-01 11:38:49 +00:00
|
|
|
// NewAccessControlDomain creates a new SubjectObjectMatcher that matches the domain as a basic string.
|
2022-10-18 08:14:34 +00:00
|
|
|
func NewAccessControlDomain(domain string) (subjcets bool, rule AccessControlDomain) {
|
2022-06-28 02:51:05 +00:00
|
|
|
m := &AccessControlDomainMatcher{}
|
2022-04-01 11:38:49 +00:00
|
|
|
domain = strings.ToLower(domain)
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(domain, "*."):
|
2022-06-28 02:51:05 +00:00
|
|
|
m.Wildcard = true
|
|
|
|
m.Name = domain[1:]
|
2022-04-01 11:38:49 +00:00
|
|
|
case strings.HasPrefix(domain, "{user}"):
|
2022-06-28 02:51:05 +00:00
|
|
|
m.UserWildcard = true
|
2022-10-18 08:14:34 +00:00
|
|
|
m.Name = domain[6:]
|
2022-04-01 11:38:49 +00:00
|
|
|
case strings.HasPrefix(domain, "{group}"):
|
2022-06-28 02:51:05 +00:00
|
|
|
m.GroupWildcard = true
|
2022-10-18 08:14:34 +00:00
|
|
|
m.Name = domain[7:]
|
2021-03-05 04:18:31 +00:00
|
|
|
default:
|
2022-06-28 02:51:05 +00:00
|
|
|
m.Name = domain
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 08:14:34 +00:00
|
|
|
return m.UserWildcard || m.GroupWildcard, AccessControlDomain{m}
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewAccessControlDomainRegex creates a new SubjectObjectMatcher that matches the domain either in a basic way or
|
|
|
|
// dynamic User/Group subexpression group way.
|
2022-09-26 04:33:08 +00:00
|
|
|
func NewAccessControlDomainRegex(pattern regexp.Regexp) (subjects bool, rule AccessControlDomain) {
|
2022-04-01 11:38:49 +00: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 04:18:31 +00:00
|
|
|
}
|
2022-04-01 11:38:49 +00:00
|
|
|
|
|
|
|
if iuser != -1 || igroup != -1 {
|
2022-09-26 04:33:08 +00:00
|
|
|
return true, AccessControlDomain{RegexpGroupStringSubjectMatcher{pattern, iuser, igroup}}
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2022-09-26 04:33:08 +00:00
|
|
|
return false, AccessControlDomain{RegexpStringSubjectMatcher{pattern}}
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 02:51:05 +00:00
|
|
|
// AccessControlDomainMatcher is the basic domain matcher.
|
|
|
|
type AccessControlDomainMatcher struct {
|
|
|
|
Name string
|
|
|
|
Wildcard bool
|
|
|
|
UserWildcard bool
|
|
|
|
GroupWildcard bool
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 02:51:05 +00: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:
|
2022-10-18 08:14:34 +00:00
|
|
|
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
|
2023-05-24 09:23:46 +00:00
|
|
|
return len(domain) > len(m.Name)
|
2022-10-18 08:14:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return domain == fmt.Sprintf("%s%s", subject.Username, m.Name)
|
2022-06-28 02:51:05 +00:00
|
|
|
case m.GroupWildcard:
|
2022-10-18 08:14:34 +00:00
|
|
|
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
|
2023-05-24 09:23:46 +00:00
|
|
|
return len(domain) > len(m.Name)
|
2022-10-18 08:14:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i := strings.Index(domain, ".")
|
2022-06-28 02:51:05 +00:00
|
|
|
|
2022-10-18 08:14:34 +00:00
|
|
|
return domain[i:] == m.Name && utils.IsStringInSliceFold(domain[:i], subject.Groups)
|
2022-06-28 02:51:05 +00:00
|
|
|
default:
|
|
|
|
return strings.EqualFold(domain, m.Name)
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
2022-06-28 02:51:05 +00:00
|
|
|
}
|
2022-04-01 11:38:49 +00:00
|
|
|
|
2022-06-28 02:51:05 +00:00
|
|
|
// AccessControlDomain represents an ACL domain.
|
|
|
|
type AccessControlDomain struct {
|
|
|
|
Matcher StringSubjectMatcher
|
2022-04-01 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 02:51:05 +00: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 04:18:31 +00:00
|
|
|
}
|