Line data Source code
1 : /*
2 : ACL utility functions
3 :
4 : Copyright (C) Nadezhda Ivanova 2010
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : /*
21 : * Name: acl_util
22 : *
23 : * Component: ldb ACL modules
24 : *
25 : * Description: Some auxiliary functions used for access checking
26 : *
27 : * Author: Nadezhda Ivanova
28 : */
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"
37 :
38 8837888 : struct security_token *acl_user_token(struct ldb_module *module)
39 : {
40 8837888 : struct ldb_context *ldb = ldb_module_get_ctx(module);
41 103430 : struct auth_session_info *session_info
42 8837888 : = (struct auth_session_info *)ldb_get_opaque(
43 : ldb,
44 : DSDB_SESSION_INFO);
45 8837888 : if(!session_info) {
46 0 : return NULL;
47 : }
48 8837880 : return session_info->security_token;
49 : }
50 :
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
54 : */
55 :
56 1482106 : 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)
62 : {
63 83812 : int ret;
64 83812 : struct ldb_result *acl_res;
65 83812 : static const char *acl_attrs[] = {
66 : "nTSecurityDescriptor",
67 : "objectSid",
68 : NULL
69 : };
70 1482106 : struct ldb_context *ldb = ldb_module_get_ctx(module);
71 83812 : struct auth_session_info *session_info
72 1482106 : = (struct auth_session_info *)ldb_get_opaque(
73 : ldb,
74 : DSDB_SESSION_INFO);
75 1482106 : if(!session_info) {
76 0 : return ldb_operr(ldb);
77 : }
78 1482106 : 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 1482106 : if (ret != LDB_SUCCESS) {
85 381 : ldb_asprintf_errstring(ldb_module_get_ctx(module),
86 : "access_check: failed to find object %s\n",
87 : ldb_dn_get_linearized(dn));
88 381 : return ret;
89 : }
90 1481725 : 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);
96 : }
97 :
98 7239225 : 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)
106 : {
107 5032 : int ret;
108 5032 : NTSTATUS status;
109 5032 : uint32_t access_granted;
110 7239225 : struct object_tree *root = NULL;
111 7239225 : struct object_tree *new_node = NULL;
112 7239225 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
113 7239225 : struct security_token *token = acl_user_token(module);
114 :
115 7239225 : if (!insert_in_object_tree(tmp_ctx,
116 : &objectclass->schemaIDGUID,
117 : access_mask, NULL,
118 : &root)) {
119 0 : DEBUG(10, ("acl_search: cannot add to object tree class schemaIDGUID\n"));
120 0 : goto fail;
121 : }
122 7239225 : new_node = root;
123 :
124 7239225 : if (!GUID_all_zero(&attr->attributeSecurityGUID)) {
125 5270849 : if (!insert_in_object_tree(tmp_ctx,
126 : &attr->attributeSecurityGUID,
127 : access_mask, new_node,
128 : &new_node)) {
129 0 : DEBUG(10, ("acl_search: cannot add to object tree securityGUID\n"));
130 0 : goto fail;
131 : }
132 : }
133 :
134 7239225 : if (!insert_in_object_tree(tmp_ctx,
135 : &attr->schemaIDGUID,
136 : access_mask, new_node,
137 : &new_node)) {
138 0 : DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));
139 0 : goto fail;
140 : }
141 :
142 7239225 : 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 7239225 : if (!NT_STATUS_IS_OK(status)) {
149 34099 : ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
150 : }
151 : else {
152 7205126 : ret = LDB_SUCCESS;
153 : }
154 7239225 : talloc_free(tmp_ctx);
155 7239225 : return ret;
156 0 : fail:
157 0 : talloc_free(tmp_ctx);
158 0 : return ldb_operr(ldb_module_get_ctx(module));
159 : }
160 :
161 114263 : 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)
168 : {
169 114263 : return acl_check_access_on_attribute_implicit_owner(module,
170 : mem_ctx,
171 : sd,
172 : rp_sid,
173 : access_mask,
174 : attr,
175 : objectclass,
176 : IMPLICIT_OWNER_READ_CONTROL_RIGHTS);
177 : }
178 :
179 42840 : 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)
185 : {
186 108 : int ret;
187 108 : NTSTATUS status;
188 108 : uint32_t access_granted;
189 42840 : struct object_tree *root = NULL;
190 42840 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
191 42840 : struct security_token *token = acl_user_token(module);
192 :
193 42840 : if (!insert_in_object_tree(tmp_ctx,
194 : &objectclass->schemaIDGUID,
195 : access_mask, NULL,
196 : &root)) {
197 0 : DEBUG(10, ("acl_search: cannot add to object tree class schemaIDGUID\n"));
198 0 : goto fail;
199 : }
200 :
201 42840 : status = sec_access_check_ds(sd, token,
202 : access_mask,
203 : &access_granted,
204 : root,
205 : rp_sid);
206 42840 : if (!NT_STATUS_IS_OK(status)) {
207 1987 : ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
208 : } else {
209 40853 : ret = LDB_SUCCESS;
210 : }
211 42840 : talloc_free(tmp_ctx);
212 42840 : return ret;
213 0 : fail:
214 0 : talloc_free(tmp_ctx);
215 0 : return ldb_operr(ldb_module_get_ctx(module));
216 : }
217 :
218 : /* checks for validated writes */
219 21264 : 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)
228 : {
229 246 : struct GUID right;
230 246 : NTSTATUS status;
231 246 : uint32_t access_granted;
232 21264 : struct object_tree *root = NULL;
233 21264 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
234 246 : static const char *no_attrs[] = { NULL };
235 21264 : struct ldb_result *extended_rights_res = NULL;
236 21264 : struct ldb_dn *extended_rights_dn = NULL;
237 21264 : struct ldb_context *ldb = ldb_module_get_ctx(module);
238 21264 : int ret = 0;
239 :
240 : /*
241 : * Find the extended right and check if applies to
242 : * the objectclass of the object
243 : */
244 21264 : extended_rights_dn = samdb_extended_rights_dn(ldb, req);
245 21264 : if (!extended_rights_dn) {
246 0 : ldb_set_errstring(ldb,
247 : "access_check: CN=Extended-Rights dn could not be generated!");
248 0 : return LDB_ERR_OPERATIONS_ERROR;
249 : }
250 :
251 : /* Note: we are checking only the structural object class. */
252 21264 : 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)));
262 :
263 21264 : if (ret != LDB_SUCCESS) {
264 0 : return ret;
265 21264 : } else if (extended_rights_res->count == 0 ) {
266 48 : ldb_debug(ldb, LDB_DEBUG_TRACE,
267 : "acl_check_extended_right: Could not find appliesTo for %s\n",
268 : ext_right);
269 48 : return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
270 : }
271 :
272 21216 : GUID_from_string(ext_right, &right);
273 :
274 21216 : if (!insert_in_object_tree(tmp_ctx, &right, right_type,
275 : NULL, &root)) {
276 0 : DEBUG(10, ("acl_ext_right: cannot add to object tree\n"));
277 0 : talloc_free(tmp_ctx);
278 0 : return LDB_ERR_OPERATIONS_ERROR;
279 : }
280 21216 : status = sec_access_check_ds(sd, token,
281 : right_type,
282 : &access_granted,
283 : root,
284 : sid);
285 :
286 21216 : if (!NT_STATUS_IS_OK(status)) {
287 331 : talloc_free(tmp_ctx);
288 331 : return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
289 : }
290 20885 : talloc_free(tmp_ctx);
291 20885 : return LDB_SUCCESS;
292 : }
293 :
294 0 : const char *acl_user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module)
295 : {
296 0 : struct ldb_context *ldb = ldb_module_get_ctx(module);
297 0 : struct auth_session_info *session_info
298 0 : = (struct auth_session_info *)ldb_get_opaque(
299 : ldb,
300 : DSDB_SESSION_INFO);
301 0 : if (!session_info) {
302 0 : return "UNKNOWN (NULL)";
303 : }
304 :
305 0 : return talloc_asprintf(mem_ctx, "%s\\%s",
306 0 : session_info->info->domain_name,
307 0 : session_info->info->account_name);
308 : }
309 :
310 32397167 : uint32_t dsdb_request_sd_flags(struct ldb_request *req, bool *explicit)
311 : {
312 1752737 : struct ldb_control *sd_control;
313 32397167 : uint32_t sd_flags = 0;
314 :
315 32397167 : if (explicit) {
316 31826063 : *explicit = false;
317 : }
318 :
319 32397167 : sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
320 32397167 : if (sd_control != NULL && sd_control->data != NULL) {
321 1342505 : struct ldb_sd_flags_control *sdctr = talloc_get_type_abort(sd_control->data, struct ldb_sd_flags_control);
322 :
323 1342505 : sd_flags = sdctr->secinfo_flags;
324 :
325 1342505 : if (explicit) {
326 1321132 : *explicit = true;
327 : }
328 :
329 : /* mark it as handled */
330 1342505 : sd_control->critical = 0;
331 : }
332 :
333 : /* we only care for the last 4 bits */
334 32397167 : sd_flags &= 0x0000000F;
335 :
336 : /*
337 : * MS-ADTS 3.1.1.3.4.1.11 says that no bits
338 : * equals all 4 bits
339 : */
340 32397167 : if (sd_flags == 0) {
341 31054716 : sd_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL;
342 : }
343 :
344 32397167 : return sd_flags;
345 : }
346 :
347 367564 : 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)
352 : {
353 367564 : struct ldb_context *ldb = ldb_module_get_ctx(module);
354 352 : struct dsdb_extended_sec_desc_propagation_op *op;
355 352 : int ret;
356 :
357 367564 : op = talloc_zero(module, struct dsdb_extended_sec_desc_propagation_op);
358 367564 : if (op == NULL) {
359 0 : return ldb_oom(ldb);
360 : }
361 :
362 367564 : op->nc_root = nc_root;
363 367564 : op->guid = guid;
364 367564 : op->include_self = include_self;
365 367564 : op->parent_guid = parent_guid;
366 :
367 367564 : ret = dsdb_module_extended(module, op, NULL,
368 : DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID,
369 : op,
370 : DSDB_FLAG_TOP_MODULE |
371 : DSDB_FLAG_AS_SYSTEM |
372 : DSDB_FLAG_TRUSTED,
373 : NULL);
374 367564 : TALLOC_FREE(op);
375 367564 : return ret;
376 : }
|