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 #include "mongo/db/auth/user.h"
32 
33 #include <vector>
34 
35 #include "mongo/db/auth/authorization_manager.h"
36 #include "mongo/db/auth/privilege.h"
37 #include "mongo/db/auth/resource_pattern.h"
38 #include "mongo/db/auth/role_name.h"
39 #include "mongo/db/auth/user_name.h"
40 #include "mongo/platform/atomic_word.h"
41 #include "mongo/util/assert_util.h"
42 #include "mongo/util/sequence_util.h"
43 
44 namespace mongo {
45 
46 namespace {
47 
computeDigest(const UserName & name)48 SHA256Block computeDigest(const UserName& name) {
49     const auto& fn = name.getFullName();
50     return SHA256Block::computeHash({ConstDataRange(fn.c_str(), fn.size())});
51 };
52 
53 }  // namespace
54 
User(const UserName & name)55 User::User(const UserName& name)
56     : _name(name), _digest(computeDigest(_name)), _refCount(0), _isValid(1) {}
57 
~User()58 User::~User() {
59     dassert(_refCount == 0);
60 }
61 
getName() const62 const UserName& User::getName() const {
63     return _name;
64 }
65 
getDigest() const66 const SHA256Block& User::getDigest() const {
67     return _digest;
68 }
69 
getRoles() const70 RoleNameIterator User::getRoles() const {
71     return makeRoleNameIteratorForContainer(_roles);
72 }
73 
getIndirectRoles() const74 RoleNameIterator User::getIndirectRoles() const {
75     return makeRoleNameIteratorForContainer(_indirectRoles);
76 }
77 
hasRole(const RoleName & roleName) const78 bool User::hasRole(const RoleName& roleName) const {
79     return _roles.count(roleName);
80 }
81 
getCredentials() const82 const User::CredentialData& User::getCredentials() const {
83     return _credentials;
84 }
85 
isValid() const86 bool User::isValid() const {
87     return _isValid.loadRelaxed() == 1;
88 }
89 
getRefCount() const90 uint32_t User::getRefCount() const {
91     return _refCount;
92 }
93 
getActionsForResource(const ResourcePattern & resource) const94 const ActionSet User::getActionsForResource(const ResourcePattern& resource) const {
95     unordered_map<ResourcePattern, Privilege>::const_iterator it = _privileges.find(resource);
96     if (it == _privileges.end()) {
97         return ActionSet();
98     }
99     return it->second.getActions();
100 }
101 
setCredentials(const CredentialData & credentials)102 void User::setCredentials(const CredentialData& credentials) {
103     _credentials = credentials;
104 }
105 
setRoles(RoleNameIterator roles)106 void User::setRoles(RoleNameIterator roles) {
107     _roles.clear();
108     while (roles.more()) {
109         _roles.insert(roles.next());
110     }
111 }
112 
setIndirectRoles(RoleNameIterator indirectRoles)113 void User::setIndirectRoles(RoleNameIterator indirectRoles) {
114     _indirectRoles.clear();
115     while (indirectRoles.more()) {
116         _indirectRoles.push_back(indirectRoles.next());
117     }
118 }
119 
setPrivileges(const PrivilegeVector & privileges)120 void User::setPrivileges(const PrivilegeVector& privileges) {
121     _privileges.clear();
122     for (size_t i = 0; i < privileges.size(); ++i) {
123         const Privilege& privilege = privileges[i];
124         _privileges[privilege.getResourcePattern()] = privilege;
125     }
126 }
127 
addRole(const RoleName & roleName)128 void User::addRole(const RoleName& roleName) {
129     _roles.insert(roleName);
130 }
131 
addRoles(const std::vector<RoleName> & roles)132 void User::addRoles(const std::vector<RoleName>& roles) {
133     for (std::vector<RoleName>::const_iterator it = roles.begin(); it != roles.end(); ++it) {
134         addRole(*it);
135     }
136 }
137 
addPrivilege(const Privilege & privilegeToAdd)138 void User::addPrivilege(const Privilege& privilegeToAdd) {
139     ResourcePrivilegeMap::iterator it = _privileges.find(privilegeToAdd.getResourcePattern());
140     if (it == _privileges.end()) {
141         // No privilege exists yet for this resource
142         _privileges.insert(std::make_pair(privilegeToAdd.getResourcePattern(), privilegeToAdd));
143     } else {
144         dassert(it->first == privilegeToAdd.getResourcePattern());
145         it->second.addActions(privilegeToAdd.getActions());
146     }
147 }
148 
addPrivileges(const PrivilegeVector & privileges)149 void User::addPrivileges(const PrivilegeVector& privileges) {
150     for (PrivilegeVector::const_iterator it = privileges.begin(); it != privileges.end(); ++it) {
151         addPrivilege(*it);
152     }
153 }
154 
setRestrictions(RestrictionDocuments restrictions)155 void User::setRestrictions(RestrictionDocuments restrictions)& {
156     _restrictions = std::move(restrictions);
157 }
158 
invalidate()159 void User::invalidate() {
160     _isValid.store(0);
161 }
162 
incrementRefCount()163 void User::incrementRefCount() {
164     ++_refCount;
165 }
166 
decrementRefCount()167 void User::decrementRefCount() {
168     dassert(_refCount > 0);
169     --_refCount;
170 }
171 }  // namespace mongo
172