1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include <iosfwd>
34 #include <string>
35 
36 #include "mongo/base/string_data.h"
37 #include "mongo/db/namespace_string.h"
38 #include "mongo/platform/hash_namespace.h"
39 
40 namespace mongo {
41 
42 /**
43  * Representation of names of various kinds of resources targetable by the access control
44  * system.
45  *
46  * Three of the types of name, "forDatabaseName", "forExactNamespace" and "forClusterResource",
47  * can represent concrete resources targeted for manipulation by database operations.  All of
48  * the types also act as patterns, useful for matching against groups of concrete resources as
49  * part of the access control system.  See buildResourceSearchList() in
50  * authorization_session.cpp for details.
51  */
52 class ResourcePattern {
53 public:
54     /**
55      * Returns a pattern that matches absolutely any resource.
56      */
forAnyResource()57     static ResourcePattern forAnyResource() {
58         return ResourcePattern(matchAnyResource);
59     }
60 
61     /**
62      * Returns a pattern that matches any database or collection resource except collections for
63      * which ns.isSystem().
64      */
forAnyNormalResource()65     static ResourcePattern forAnyNormalResource() {
66         return ResourcePattern(matchAnyNormalResource);
67     }
68 
69     /**
70      * Returns a pattern that matches the "cluster" resource.
71      */
forClusterResource()72     static ResourcePattern forClusterResource() {
73         return ResourcePattern(matchClusterResource);
74     }
75 
76     /**
77      * Returns a pattern that matches the named database, and NamespaceStrings
78      * "ns" for which ns.isSystem() is false and ns.db() == dbname.
79      */
forDatabaseName(StringData dbName)80     static ResourcePattern forDatabaseName(StringData dbName) {
81         return ResourcePattern(matchDatabaseName, NamespaceString(dbName, ""));
82     }
83 
84     /**
85      * Returns a pattern that matches NamespaceStrings "ns" for which ns.coll() ==
86      * collectionName.
87      */
forCollectionName(StringData collectionName)88     static ResourcePattern forCollectionName(StringData collectionName) {
89         return ResourcePattern(matchCollectionName, NamespaceString("", collectionName));
90     }
91 
92     /**
93      * Returns a pattern that matches the given exact namespace string.
94      */
forExactNamespace(const NamespaceString & ns)95     static ResourcePattern forExactNamespace(const NamespaceString& ns) {
96         return ResourcePattern(matchExactNamespace, ns);
97     }
98 
99     /**
100      * Constructs a pattern that never matches.
101      */
ResourcePattern()102     ResourcePattern() : _matchType(matchNever) {}
103 
104     /**
105      * Returns true if this pattern matches only exact namespaces.
106      */
isExactNamespacePattern()107     bool isExactNamespacePattern() const {
108         return _matchType == matchExactNamespace;
109     }
110 
111     /**
112      * Returns true if this pattern matches on the database name only.
113      */
isDatabasePattern()114     bool isDatabasePattern() const {
115         return _matchType == matchDatabaseName;
116     }
117 
118     /**
119      * Returns true if this pattern matches on the collection name only.
120      */
isCollectionPattern()121     bool isCollectionPattern() const {
122         return _matchType == matchCollectionName;
123     }
124 
125     /**
126      * Returns true if this pattern matches the cluster resource only.
127      */
isClusterResourcePattern()128     bool isClusterResourcePattern() const {
129         return _matchType == matchClusterResource;
130     }
131 
132     /**
133      * Returns true if this pattern matches only any normal resource.
134      */
isAnyNormalResourcePattern()135     bool isAnyNormalResourcePattern() const {
136         return _matchType == matchAnyNormalResource;
137     }
138 
139     /**
140      * Returns true if this pattern matches any resource.
141      */
isAnyResourcePattern()142     bool isAnyResourcePattern() const {
143         return _matchType == matchAnyResource;
144     }
145 
146     /**
147      * Returns the namespace that this pattern matches.
148      *
149      * Behavior is undefined unless isExactNamespacePattern() is true.
150      */
ns()151     const NamespaceString& ns() const {
152         return _ns;
153     }
154 
155     /**
156      * Returns the database that this pattern matches.
157      *
158      * Behavior is undefined unless the pattern is of type matchDatabaseName or
159      * matchExactNamespace
160      */
databaseToMatch()161     StringData databaseToMatch() const {
162         return _ns.db();
163     }
164 
165     /**
166      * Returns the collection that this pattern matches.
167      *
168      * Behavior is undefined unless the pattern is of type matchCollectionName or
169      * matchExactNamespace
170      */
collectionToMatch()171     StringData collectionToMatch() const {
172         return _ns.coll();
173     }
174 
175     std::string toString() const;
176 
hash()177     inline size_t hash() const {
178         // TODO: Choose a better hash function.
179         return MONGO_HASH_NAMESPACE::hash<std::string>()(_ns.ns()) ^ _matchType;
180     }
181 
182     bool operator==(const ResourcePattern& other) const {
183         if (_matchType != other._matchType)
184             return false;
185         if (_ns != other._ns)
186             return false;
187         return true;
188     }
189 
190 private:
191     enum MatchType {
192         matchNever = 0,              /// Matches no resource.
193         matchClusterResource = 1,    /// Matches if the resource is the cluster resource.
194         matchDatabaseName = 2,       /// Matches if the resource's database name is _ns.db().
195         matchCollectionName = 3,     /// Matches if the resource's collection name is _ns.coll().
196         matchExactNamespace = 4,     /// Matches if the resource's namespace name is _ns.
197         matchAnyNormalResource = 5,  /// Matches all databases and non-system collections.
198         matchAnyResource = 6         /// Matches absolutely anything.
199     };
200 
ResourcePattern(MatchType type)201     explicit ResourcePattern(MatchType type) : _matchType(type) {}
ResourcePattern(MatchType type,const NamespaceString & ns)202     ResourcePattern(MatchType type, const NamespaceString& ns) : _matchType(type), _ns(ns) {}
203 
204     MatchType _matchType;
205     NamespaceString _ns;
206 };
207 
208 std::ostream& operator<<(std::ostream& os, const ResourcePattern& pattern);
209 
210 }  // namespace mongo
211 
212 MONGO_HASH_NAMESPACE_START
213 template <>
214 struct hash<mongo::ResourcePattern> {
215     size_t operator()(const mongo::ResourcePattern& resource) const {
216         return resource.hash();
217     }
218 };
219 MONGO_HASH_NAMESPACE_END
220