sync machine password to keytab: handle FreeIPA use case
[Samba.git] / source4 / dsdb / samdb / ldb_modules / acl_util.c
blob352997ef643ae41dfd6766fc22a30a0584cc4099
1 /*
2 ACL utility functions
4 Copyright (C) Nadezhda Ivanova 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * Name: acl_util
23 * Component: ldb ACL modules
25 * Description: Some auxiliary functions used for access checking
27 * Author: Nadezhda Ivanova
29 #include "includes.h"
30 #include "ldb_module.h"
31 #include "auth/auth.h"
32 #include "libcli/security/security.h"
33 #include "dsdb/samdb/samdb.h"
34 #include "librpc/gen_ndr/ndr_security.h"
35 #include "param/param.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
38 struct security_token *acl_user_token(struct ldb_module *module)
40 struct ldb_context *ldb = ldb_module_get_ctx(module);
41 struct auth_session_info *session_info
42 = (struct auth_session_info *)ldb_get_opaque(
43 ldb,
44 DSDB_SESSION_INFO);
45 if(!session_info) {
46 return NULL;
48 return session_info->security_token;
51 /* performs an access check from inside the module stack
52 * given the dn of the object to be checked, the required access
53 * guid is either the guid of the extended right, or NULL
56 int dsdb_module_check_access_on_dn(struct ldb_module *module,
57 TALLOC_CTX *mem_ctx,
58 struct ldb_dn *dn,
59 uint32_t access_mask,
60 const struct GUID *guid,
61 struct ldb_request *parent)
63 int ret;
64 struct ldb_result *acl_res;
65 static const char *acl_attrs[] = {
66 "nTSecurityDescriptor",
67 "objectSid",
68 NULL
70 struct ldb_context *ldb = ldb_module_get_ctx(module);
71 struct auth_session_info *session_info
72 = (struct auth_session_info *)ldb_get_opaque(
73 ldb,
74 DSDB_SESSION_INFO);
75 if(!session_info) {
76 return ldb_operr(ldb);
78 ret = dsdb_module_search_dn(module, mem_ctx, &acl_res, dn,
79 acl_attrs,
80 DSDB_FLAG_NEXT_MODULE |
81 DSDB_FLAG_AS_SYSTEM |
82 DSDB_SEARCH_SHOW_RECYCLED,
83 parent);
84 if (ret != LDB_SUCCESS) {
85 ldb_asprintf_errstring(ldb_module_get_ctx(module),
86 "access_check: failed to find object %s\n",
87 ldb_dn_get_linearized(dn));
88 return ret;
90 return dsdb_check_access_on_dn_internal(ldb, acl_res,
91 mem_ctx,
92 session_info->security_token,
93 dn,
94 access_mask,
95 guid);
98 int acl_check_access_on_attribute_implicit_owner(struct ldb_module *module,
99 TALLOC_CTX *mem_ctx,
100 const struct security_descriptor *sd,
101 const struct dom_sid *rp_sid,
102 uint32_t access_mask,
103 const struct dsdb_attribute *attr,
104 const struct dsdb_class *objectclass,
105 enum implicit_owner_rights implicit_owner_rights)
107 int ret;
108 NTSTATUS status;
109 uint32_t access_granted;
110 struct object_tree *root = NULL;
111 struct object_tree *new_node = NULL;
112 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
113 struct security_token *token = acl_user_token(module);
115 if (!insert_in_object_tree(tmp_ctx,
116 &objectclass->schemaIDGUID,
117 access_mask, NULL,
118 &root)) {
119 DEBUG(10, ("acl_search: cannot add to object tree class schemaIDGUID\n"));
120 goto fail;
122 new_node = root;
124 if (!GUID_all_zero(&attr->attributeSecurityGUID)) {
125 if (!insert_in_object_tree(tmp_ctx,
126 &attr->attributeSecurityGUID,
127 access_mask, new_node,
128 &new_node)) {
129 DEBUG(10, ("acl_search: cannot add to object tree securityGUID\n"));
130 goto fail;
134 if (!insert_in_object_tree(tmp_ctx,
135 &attr->schemaIDGUID,
136 access_mask, new_node,
137 &new_node)) {
138 DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));
139 goto fail;
142 status = sec_access_check_ds_implicit_owner(sd, token,
143 access_mask,
144 &access_granted,
145 root,
146 rp_sid,
147 implicit_owner_rights);
148 if (!NT_STATUS_IS_OK(status)) {
149 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
151 else {
152 ret = LDB_SUCCESS;
154 talloc_free(tmp_ctx);
155 return ret;
156 fail:
157 talloc_free(tmp_ctx);
158 return ldb_operr(ldb_module_get_ctx(module));
161 int acl_check_access_on_attribute(struct ldb_module *module,
162 TALLOC_CTX *mem_ctx,
163 struct security_descriptor *sd,
164 struct dom_sid *rp_sid,
165 uint32_t access_mask,
166 const struct dsdb_attribute *attr,
167 const struct dsdb_class *objectclass)
169 return acl_check_access_on_attribute_implicit_owner(module,
170 mem_ctx,
172 rp_sid,
173 access_mask,
174 attr,
175 objectclass,
176 IMPLICIT_OWNER_READ_CONTROL_RIGHTS);
179 int acl_check_access_on_objectclass(struct ldb_module *module,
180 TALLOC_CTX *mem_ctx,
181 struct security_descriptor *sd,
182 struct dom_sid *rp_sid,
183 uint32_t access_mask,
184 const struct dsdb_class *objectclass)
186 int ret;
187 NTSTATUS status;
188 uint32_t access_granted;
189 struct object_tree *root = NULL;
190 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
191 struct security_token *token = acl_user_token(module);
193 if (!insert_in_object_tree(tmp_ctx,
194 &objectclass->schemaIDGUID,
195 access_mask, NULL,
196 &root)) {
197 DEBUG(10, ("acl_search: cannot add to object tree class schemaIDGUID\n"));
198 goto fail;
201 status = sec_access_check_ds(sd, token,
202 access_mask,
203 &access_granted,
204 root,
205 rp_sid);
206 if (!NT_STATUS_IS_OK(status)) {
207 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
208 } else {
209 ret = LDB_SUCCESS;
211 talloc_free(tmp_ctx);
212 return ret;
213 fail:
214 talloc_free(tmp_ctx);
215 return ldb_operr(ldb_module_get_ctx(module));
218 /* checks for validated writes */
219 int acl_check_extended_right(TALLOC_CTX *mem_ctx,
220 struct ldb_module *module,
221 struct ldb_request *req,
222 const struct dsdb_class *objectclass,
223 struct security_descriptor *sd,
224 struct security_token *token,
225 const char *ext_right,
226 uint32_t right_type,
227 struct dom_sid *sid)
229 struct GUID right;
230 NTSTATUS status;
231 uint32_t access_granted;
232 struct object_tree *root = NULL;
233 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
234 static const char *no_attrs[] = { NULL };
235 struct ldb_result *extended_rights_res = NULL;
236 struct ldb_dn *extended_rights_dn = NULL;
237 struct ldb_context *ldb = ldb_module_get_ctx(module);
238 int ret = 0;
241 * Find the extended right and check if applies to
242 * the objectclass of the object
244 extended_rights_dn = samdb_extended_rights_dn(ldb, req);
245 if (!extended_rights_dn) {
246 ldb_set_errstring(ldb,
247 "access_check: CN=Extended-Rights dn could not be generated!");
248 return LDB_ERR_OPERATIONS_ERROR;
251 /* Note: we are checking only the structural object class. */
252 ret = dsdb_module_search(module, req, &extended_rights_res,
253 extended_rights_dn, LDB_SCOPE_ONELEVEL,
254 no_attrs,
255 DSDB_FLAG_NEXT_MODULE |
256 DSDB_FLAG_AS_SYSTEM,
257 req,
258 "(&(rightsGuid=%s)(appliesTo=%s))",
259 ext_right,
260 GUID_string(tmp_ctx,
261 &(objectclass->schemaIDGUID)));
263 if (ret != LDB_SUCCESS) {
264 return ret;
265 } else if (extended_rights_res->count == 0 ) {
266 ldb_debug(ldb, LDB_DEBUG_TRACE,
267 "acl_check_extended_right: Could not find appliesTo for %s\n",
268 ext_right);
269 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
272 GUID_from_string(ext_right, &right);
274 if (!insert_in_object_tree(tmp_ctx, &right, right_type,
275 NULL, &root)) {
276 DEBUG(10, ("acl_ext_right: cannot add to object tree\n"));
277 talloc_free(tmp_ctx);
278 return LDB_ERR_OPERATIONS_ERROR;
280 status = sec_access_check_ds(sd, token,
281 right_type,
282 &access_granted,
283 root,
284 sid);
286 if (!NT_STATUS_IS_OK(status)) {
287 talloc_free(tmp_ctx);
288 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
290 talloc_free(tmp_ctx);
291 return LDB_SUCCESS;
294 const char *acl_user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module)
296 struct ldb_context *ldb = ldb_module_get_ctx(module);
297 struct auth_session_info *session_info
298 = (struct auth_session_info *)ldb_get_opaque(
299 ldb,
300 DSDB_SESSION_INFO);
301 if (!session_info) {
302 return "UNKNOWN (NULL)";
305 return talloc_asprintf(mem_ctx, "%s\\%s",
306 session_info->info->domain_name,
307 session_info->info->account_name);
310 uint32_t dsdb_request_sd_flags(struct ldb_request *req, bool *explicit)
312 struct ldb_control *sd_control;
313 uint32_t sd_flags = 0;
315 if (explicit) {
316 *explicit = false;
319 sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
320 if (sd_control != NULL && sd_control->data != NULL) {
321 struct ldb_sd_flags_control *sdctr = talloc_get_type_abort(sd_control->data, struct ldb_sd_flags_control);
323 sd_flags = sdctr->secinfo_flags;
325 if (explicit) {
326 *explicit = true;
329 /* mark it as handled */
330 sd_control->critical = 0;
333 /* we only care for the last 4 bits */
334 sd_flags &= 0x0000000F;
337 * MS-ADTS 3.1.1.3.4.1.11 says that no bits
338 * equals all 4 bits
340 if (sd_flags == 0) {
341 sd_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL;
344 return sd_flags;
347 int dsdb_module_schedule_sd_propagation(struct ldb_module *module,
348 struct ldb_dn *nc_root,
349 struct GUID guid,
350 struct GUID parent_guid,
351 bool include_self)
353 struct ldb_context *ldb = ldb_module_get_ctx(module);
354 struct dsdb_extended_sec_desc_propagation_op *op;
355 int ret;
357 op = talloc_zero(module, struct dsdb_extended_sec_desc_propagation_op);
358 if (op == NULL) {
359 return ldb_oom(ldb);
362 op->nc_root = nc_root;
363 op->guid = guid;
364 op->include_self = include_self;
365 op->parent_guid = parent_guid;
367 ret = dsdb_module_extended(module, op, NULL,
368 DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID,
370 DSDB_FLAG_TOP_MODULE |
371 DSDB_FLAG_AS_SYSTEM |
372 DSDB_FLAG_TRUSTED,
373 NULL);
374 TALLOC_FREE(op);
375 return ret;