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 <string>
34 #include <vector>
35 
36 #include "mongo/base/disallow_copying.h"
37 #include "mongo/db/auth/privilege.h"
38 #include "mongo/db/auth/resource_pattern.h"
39 #include "mongo/db/auth/restriction_set.h"
40 #include "mongo/db/auth/role_name.h"
41 #include "mongo/db/auth/user_name.h"
42 #include "mongo/platform/atomic_word.h"
43 #include "mongo/platform/unordered_map.h"
44 #include "mongo/platform/unordered_set.h"
45 
46 namespace mongo {
47 
48 /**
49  * Represents a MongoDB user.  Stores information about the user necessary for access control
50  * checks and authentications, such as what privileges this user has, as well as what roles
51  * the user belongs to.
52  *
53  * Every User object is owned by an AuthorizationManager.  The AuthorizationManager is the only
54  * one that should construct, modify, or delete a User object.  All other consumers of User must
55  * use only the const methods.  The AuthorizationManager is responsible for maintaining the
56  * reference count on all User objects it gives out and must not mutate any User objects with
57  * a non-zero reference count (except to call invalidate()).  Any consumer of a User object
58  * should check isInvalidated() before using it, and if it has been invalidated, it should
59  * return the object to the AuthorizationManager and fetch a new User object instance for this
60  * user from the AuthorizationManager.
61  */
62 class User {
63     MONGO_DISALLOW_COPYING(User);
64 
65 public:
66     struct SCRAMCredentials {
SCRAMCredentialsSCRAMCredentials67         SCRAMCredentials() : iterationCount(0), salt(""), serverKey(""), storedKey("") {}
68 
69         int iterationCount;
70         std::string salt;
71         std::string serverKey;
72         std::string storedKey;
73 
isValidSCRAMCredentials74         bool isValid() const {
75             // 160bit -> 20octets -> * 4/3 -> 26.667 -> padded to 28
76             const size_t kEncodedSHA1Length = 28;
77             // 128bit -> 16octets -> * 4/3 -> 21.333 -> padded to 24
78             const size_t kEncodedSaltLength = 24;
79 
80             return (salt.size() == kEncodedSaltLength) && base64::validate(salt) &&
81                 (serverKey.size() == kEncodedSHA1Length) && base64::validate(serverKey) &&
82                 (storedKey.size() == kEncodedSHA1Length) && base64::validate(storedKey);
83         }
84     };
85     struct CredentialData {
CredentialDataCredentialData86         CredentialData() : password(""), scram(), isExternal(false) {}
87 
88         std::string password;
89         SCRAMCredentials scram;
90         bool isExternal;
91     };
92 
93     typedef unordered_map<ResourcePattern, Privilege> ResourcePrivilegeMap;
94 
95     explicit User(const UserName& name);
96     ~User();
97 
98     using UserId = std::vector<std::uint8_t>;
getID()99     const UserId& getID() const {
100         return _id;
101     }
102 
setID(UserId id)103     void setID(UserId id) {
104         _id = std::move(id);
105     }
106 
107     /**
108      * Returns the user name for this user.
109      */
110     const UserName& getName() const;
111 
112     /**
113      * Returns a digest of the user's identity
114      */
115     const SHA256Block& getDigest() const;
116 
117     /**
118      * Returns an iterator over the names of the user's direct roles
119      */
120     RoleNameIterator getRoles() const;
121 
122     /**
123      * Returns an iterator over the names of the user's indirect roles
124      */
125     RoleNameIterator getIndirectRoles() const;
126 
127     /**
128      * Returns true if this user is a member of the given role.
129      */
130     bool hasRole(const RoleName& roleName) const;
131 
132     /**
133      * Returns a reference to the information about the user's privileges.
134      */
getPrivileges()135     const ResourcePrivilegeMap& getPrivileges() const {
136         return _privileges;
137     }
138 
139     /**
140      * Returns the CredentialData for this user.
141      */
142     const CredentialData& getCredentials() const;
143 
144     /**
145      * Gets the set of actions this user is allowed to perform on the given resource.
146      */
147     const ActionSet getActionsForResource(const ResourcePattern& resource) const;
148 
149     /**
150      * Returns true if this copy of information about this user is still valid. If this returns
151      * false, this object should no longer be used and should be returned to the
152      * AuthorizationManager and a new User object for this user should be requested.
153      */
154     bool isValid() const;
155 
156     /**
157      * This returns the reference count for this User.  The AuthorizationManager should be the
158      * only caller of this.
159      */
160     uint32_t getRefCount() const;
161 
162     // Mutators below.  Mutation functions should *only* be called by the AuthorizationManager
163 
164     /**
165      * Sets this user's authentication credentials.
166      */
167     void setCredentials(const CredentialData& credentials);
168 
169     /**
170      * Replaces any existing user role membership information with the roles from "roles".
171      */
172     void setRoles(RoleNameIterator roles);
173 
174     /**
175      * Replaces any existing indirect user role membership information with the roles from
176      * "indirectRoles".
177      */
178     void setIndirectRoles(RoleNameIterator indirectRoles);
179 
180     /**
181      * Replaces any existing user privilege information with "privileges".
182      */
183     void setPrivileges(const PrivilegeVector& privileges);
184 
185     /**
186      * Adds the given role name to the list of roles of which this user is a member.
187      */
188     void addRole(const RoleName& role);
189 
190     /**
191      * Adds the given role names to the list of roles that this user belongs to.
192      */
193     void addRoles(const std::vector<RoleName>& roles);
194 
195     /**
196      * Adds the given privilege to the list of privileges this user is authorized for.
197      */
198     void addPrivilege(const Privilege& privilege);
199 
200     /**
201      * Adds the given privileges to the list of privileges this user is authorized for.
202      */
203     void addPrivileges(const PrivilegeVector& privileges);
204 
205     /**
206      * Replaces any existing authentication restrictions with "restrictions".
207      */
208     void setRestrictions(RestrictionDocuments restrictions) &;
209 
210     /**
211      * Gets any set authentication restrictions.
212      */
getRestrictions()213     const RestrictionDocuments& getRestrictions() const& noexcept {
214         return _restrictions;
215     }
216     void getRestrictions() && = delete;
217 
218     /**
219      * Marks this instance of the User object as invalid, most likely because information about
220      * the user has been updated and needs to be reloaded from the AuthorizationManager.
221      *
222      * This method should *only* be called by the AuthorizationManager.
223      */
224     void invalidate();
225 
226     /**
227      * Increments the reference count for this User object, which records how many threads have
228      * a reference to it.
229      *
230      * This method should *only* be called by the AuthorizationManager.
231      */
232     void incrementRefCount();
233 
234     /**
235      * Decrements the reference count for this User object, which records how many threads have
236      * a reference to it.  Once the reference count goes to zero, the AuthorizationManager is
237      * allowed to destroy this instance.
238      *
239      * This method should *only* be called by the AuthorizationManager.
240      */
241     void decrementRefCount();
242 
243 private:
244     // Unique ID (often UUID) for this user.
245     // May be empty for legacy users.
246     UserId _id;
247 
248     UserName _name;
249 
250     // Digest of the full username
251     SHA256Block _digest;
252 
253     // Maps resource name to privilege on that resource
254     ResourcePrivilegeMap _privileges;
255 
256     // Roles the user has privileges from
257     unordered_set<RoleName> _roles;
258 
259     // Roles that the user indirectly has privileges from, due to role inheritance.
260     std::vector<RoleName> _indirectRoles;
261 
262     // Credential information.
263     CredentialData _credentials;
264 
265     // Restrictions which must be met by a Client in order to authenticate as this user.
266     RestrictionDocuments _restrictions;
267 
268     // _refCount and _isInvalidated are modified exclusively by the AuthorizationManager
269     // _isInvalidated can be read by any consumer of User, but _refCount can only be
270     // meaningfully read by the AuthorizationManager, as _refCount is guarded by the AM's _lock
271     uint32_t _refCount;
272     AtomicUInt32 _isValid;  // Using as a boolean
273 };
274 
275 }  // namespace mongo
276