package authorization import ( "fmt" "net" "net/url" "strings" "github.com/authelia/authelia/v4/internal/utils" ) type AccessControlNetworks []*net.IPNet func (a AccessControlNetworks) IsMatch(subject Subject) bool { if len(a) == 0 { return true } for _, network := range a { if network.Contains(subject.IP) { return true } } return false } // SubjectMatcher is a matcher that takes a subject. type SubjectMatcher interface { IsMatch(subject Subject) (match bool) } // StringSubjectMatcher is a matcher that takes an input string and subject. type StringSubjectMatcher interface { IsMatch(input string, subject Subject) (match bool) } // SubjectObjectMatcher is a matcher that takes both a subject and an object. type SubjectObjectMatcher interface { IsMatch(subject Subject, object Object) (match bool) } // ObjectMatcher is a matcher that takes an object. type ObjectMatcher interface { IsMatch(object Object) (match bool) } // Subject represents the identity of a user for the purposes of ACL matching. type Subject struct { Username string Groups []string ClientID string IP net.IP } // String returns a string representation of the Subject. func (s Subject) String() string { return fmt.Sprintf("username=%s groups=%s ip=%s", s.Username, strings.Join(s.Groups, ","), s.IP.String()) } // IsAnonymous returns true if the Subject username and groups are empty. func (s Subject) IsAnonymous() bool { return s.Username == "" && len(s.Groups) == 0 } // Object represents a protected object for the purposes of ACL matching. type Object struct { URL *url.URL Domain string Path string Method string } // String is a string representation of the Object. func (o Object) String() string { if o.URL == nil { return "" } return o.URL.String() } // NewObjectRaw creates a new Object type from a URL and a method header. func NewObjectRaw(targetURL *url.URL, method []byte) (object Object) { return NewObject(targetURL, string(method)) } // NewObject creates a new Object type from a URL and a method header. func NewObject(targetURL *url.URL, method string) (object Object) { return Object{ URL: targetURL, Domain: targetURL.Hostname(), Path: utils.URLPathFullClean(targetURL), Method: method, } } // RuleMatchResult describes how well a rule matched a subject/object combo. type RuleMatchResult struct { Rule *AccessControlRule Skipped bool MatchDomain bool MatchResources bool MatchQuery bool MatchMethods bool MatchNetworks bool MatchSubjects bool MatchSubjectsExact bool } // IsMatch returns true if all the criteria matched. func (r RuleMatchResult) IsMatch() (match bool) { return r.MatchDomain && r.MatchResources && r.MatchQuery && r.MatchMethods && r.MatchNetworks && r.MatchSubjectsExact } // IsPotentialMatch returns true if the rule is potentially a match. func (r RuleMatchResult) IsPotentialMatch() (match bool) { return r.MatchDomain && r.MatchResources && r.MatchQuery && r.MatchMethods && r.MatchNetworks && r.MatchSubjects && !r.MatchSubjectsExact }