• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/dsdb/samdb/ldb_modules/
1/*
2   ldb database library
3
4   Copyright (C) Simo Sorce  2006-2008
5   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
6   Copyright (C) Nadezhda Ivanova  2009
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22/*
23 *  Name: ldb
24 *
25 *  Component: DS Security descriptor module
26 *
27 *  Description:
28 *  - Calculate the security descriptor of a newly created object
29 *  - Perform sd recalculation on a move operation
30 *  - Handle sd modification invariants
31 *
32 *  Author: Nadezhda Ivanova
33 */
34
35#include "includes.h"
36#include "ldb_module.h"
37#include "dlinklist.h"
38#include "dsdb/samdb/samdb.h"
39#include "librpc/ndr/libndr.h"
40#include "librpc/gen_ndr/ndr_security.h"
41#include "libcli/security/security.h"
42#include "auth/auth.h"
43#include "param/param.h"
44
45struct descriptor_data {
46	int _dummy;
47};
48
49struct descriptor_context {
50		struct ldb_module *module;
51		struct ldb_request *req;
52		struct ldb_reply *search_res;
53		int (*step_fn)(struct descriptor_context *);
54};
55
56static const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema, struct ldb_message_element *element)
57{
58	const struct dsdb_class *last_class = NULL;
59	int i;
60	for (i = 0; i < element->num_values; i++){
61		if (!last_class) {
62			last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
63		} else {
64			const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
65			if (tmp_class->subClass_order > last_class->subClass_order)
66				last_class = tmp_class;
67		}
68	}
69	return last_class;
70}
71
72struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
73			       struct ldb_dn *dn,
74			       struct security_token *token,
75			       struct ldb_context *ldb)
76{
77	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
78	struct ldb_dn *root_base_dn = ldb_get_root_basedn(ldb);
79	struct ldb_dn *schema_base_dn = ldb_get_schema_basedn(ldb);
80	struct ldb_dn *config_base_dn = ldb_get_config_basedn(ldb);
81	const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
82	struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
83	struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS);
84	struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS);
85	struct dom_sid *dag_sid;
86
87	if (ldb_dn_compare_base(schema_base_dn, dn) == 0){
88		if (security_token_has_sid(token, sa_sid))
89			dag_sid = dom_sid_dup(mem_ctx, sa_sid);
90		else if (security_token_has_sid(token, ea_sid))
91			dag_sid = dom_sid_dup(mem_ctx, ea_sid);
92		else if (security_token_has_sid(token, da_sid))
93			dag_sid = dom_sid_dup(mem_ctx, da_sid);
94		else
95			dag_sid = NULL;
96	}
97	else if (ldb_dn_compare_base(config_base_dn, dn) == 0){
98		if (security_token_has_sid(token, ea_sid))
99			dag_sid = dom_sid_dup(mem_ctx, ea_sid);
100		else if (security_token_has_sid(token, da_sid))
101			dag_sid = dom_sid_dup(mem_ctx, da_sid);
102		else
103			dag_sid = NULL;
104	}
105	else if (ldb_dn_compare_base(root_base_dn, dn) == 0){
106		if (security_token_has_sid(token, da_sid))
107			dag_sid = dom_sid_dup(mem_ctx, da_sid);
108		else if (security_token_has_sid(token, ea_sid))
109				dag_sid = dom_sid_dup(mem_ctx, ea_sid);
110		else
111			dag_sid = NULL;
112	}
113	else
114		dag_sid = NULL;
115
116	talloc_free(tmp_ctx);
117	return dag_sid;
118}
119
120static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx,
121					    const struct dsdb_class *objectclass)
122{
123	struct ldb_context *ldb = ldb_module_get_ctx(module);
124	struct security_descriptor *sd;
125	const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
126
127	if (!objectclass->defaultSecurityDescriptor || !domain_sid) {
128		return NULL;
129	}
130
131	sd = sddl_decode(mem_ctx,
132			 objectclass->defaultSecurityDescriptor,
133			 domain_sid);
134	return sd;
135}
136
137static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
138					 struct ldb_context *ldb,
139					 struct dom_sid *dag)
140{
141	int *domainFunctionality;
142
143	domainFunctionality = talloc_get_type(
144		ldb_get_opaque(ldb, "domainFunctionality"), int);
145
146	if (*domainFunctionality
147			&& (*domainFunctionality >= DS_DOMAIN_FUNCTION_2008)) {
148		return dag;
149	}
150
151	return NULL;
152}
153
154static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
155				     struct ldb_dn *dn,
156				     TALLOC_CTX *mem_ctx,
157				     const struct dsdb_class *objectclass,
158				     const struct ldb_val *parent,
159				     struct ldb_val *object)
160{
161	struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
162	struct security_descriptor *new_sd;
163	DATA_BLOB *linear_sd;
164	enum ndr_err_code ndr_err;
165	struct ldb_context *ldb = ldb_module_get_ctx(module);
166	struct auth_session_info *session_info
167		= ldb_get_opaque(ldb, "sessionInfo");
168	const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
169	char *sddl_sd;
170	struct dom_sid *default_owner;
171	struct dom_sid *default_group;
172
173	if (object) {
174		user_descriptor = talloc(mem_ctx, struct security_descriptor);
175		if(!user_descriptor)
176			return NULL;
177		ndr_err = ndr_pull_struct_blob(object, user_descriptor, NULL,
178					       user_descriptor,
179					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
180
181		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){
182			talloc_free(user_descriptor);
183			return NULL;
184		}
185	} else {
186		user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
187	}
188
189	if (parent){
190		parent_descriptor = talloc(mem_ctx, struct security_descriptor);
191		if(!parent_descriptor)
192			return NULL;
193		ndr_err = ndr_pull_struct_blob(parent, parent_descriptor, NULL,
194					       parent_descriptor,
195					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
196
197		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){
198			talloc_free(parent_descriptor);
199			return NULL;
200		}
201	}
202	default_owner = get_default_ag(mem_ctx, dn,
203				       session_info->security_token, ldb);
204	default_group = get_default_group(mem_ctx, ldb, default_owner);
205	new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true,
206					    NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT,
207					    session_info->security_token,
208					    default_owner, default_group,
209					    map_generic_rights_ds);
210	if (!new_sd)
211		return NULL;
212
213
214	sddl_sd = sddl_encode(mem_ctx, new_sd, domain_sid);
215	DEBUG(10, ("Object %s created with desriptor %s", ldb_dn_get_linearized(dn), sddl_sd));
216
217	linear_sd = talloc(mem_ctx, DATA_BLOB);
218	if (!linear_sd) {
219		return NULL;
220	}
221
222	ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
223				       lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
224				       new_sd,
225				       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
226	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
227		return NULL;
228	}
229
230	return linear_sd;
231}
232
233static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
234							  struct ldb_request *req)
235{
236	struct ldb_context *ldb;
237	struct descriptor_context *ac;
238
239	ldb = ldb_module_get_ctx(module);
240
241	ac = talloc_zero(req, struct descriptor_context);
242	if (ac == NULL) {
243		ldb_set_errstring(ldb, "Out of Memory");
244		return NULL;
245	}
246
247	ac->module = module;
248	ac->req = req;
249	return ac;
250}
251
252static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares)
253{
254	struct ldb_context *ldb;
255	struct descriptor_context *ac;
256	int ret;
257
258	ac = talloc_get_type(req->context, struct descriptor_context);
259	ldb = ldb_module_get_ctx(ac->module);
260
261	if (!ares) {
262		return ldb_module_done(ac->req, NULL, NULL,
263					LDB_ERR_OPERATIONS_ERROR);
264	}
265	if (ares->error != LDB_SUCCESS &&
266	    ares->error != LDB_ERR_NO_SUCH_OBJECT) {
267		return ldb_module_done(ac->req, ares->controls,
268					ares->response, ares->error);
269	}
270
271	ldb_reset_err_string(ldb);
272
273	switch (ares->type) {
274	case LDB_REPLY_ENTRY:
275		if (ac->search_res != NULL) {
276			ldb_set_errstring(ldb, "Too many results");
277			talloc_free(ares);
278			return ldb_module_done(ac->req, NULL, NULL,
279						LDB_ERR_OPERATIONS_ERROR);
280		}
281
282		ac->search_res = talloc_steal(ac, ares);
283		break;
284
285	case LDB_REPLY_REFERRAL:
286		/* ignore */
287		talloc_free(ares);
288		break;
289
290	case LDB_REPLY_DONE:
291		talloc_free(ares);
292		ret = ac->step_fn(ac);
293		if (ret != LDB_SUCCESS) {
294			return ldb_module_done(ac->req, NULL, NULL, ret);
295		}
296		break;
297	}
298
299	return LDB_SUCCESS;
300}
301static int descriptor_op_callback(struct ldb_request *req, struct ldb_reply *ares)
302{
303	struct descriptor_context *ac;
304
305	ac = talloc_get_type(req->context, struct descriptor_context);
306
307	if (!ares) {
308		return ldb_module_done(ac->req, NULL, NULL,
309					LDB_ERR_OPERATIONS_ERROR);
310	}
311	if (ares->error != LDB_SUCCESS) {
312		return ldb_module_done(ac->req, ares->controls,
313					ares->response, ares->error);
314	}
315
316	if (ares->type != LDB_REPLY_DONE) {
317		talloc_free(ares);
318		return ldb_module_done(ac->req, NULL, NULL,
319					LDB_ERR_OPERATIONS_ERROR);
320	}
321
322	return ldb_module_done(ac->req, ares->controls,
323				ares->response, ares->error);
324}
325
326static int descriptor_do_add(struct descriptor_context *ac)
327{
328	struct ldb_context *ldb;
329	const struct dsdb_schema *schema;
330	struct ldb_request *add_req;
331	struct ldb_message_element *objectclass_element, *sd_element = NULL;
332	struct ldb_message *msg;
333	TALLOC_CTX *mem_ctx;
334	int ret;
335	struct ldb_val *sd_val = NULL;
336	const struct ldb_val *parentsd_val = NULL;
337	DATA_BLOB *sd;
338	const struct dsdb_class *objectclass;
339
340	ldb = ldb_module_get_ctx(ac->module);
341	schema = dsdb_get_schema(ldb);
342
343	mem_ctx = talloc_new(ac);
344	if (mem_ctx == NULL) {
345		return LDB_ERR_OPERATIONS_ERROR;
346	}
347
348	msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
349
350	/* get the security descriptor values*/
351	sd_element = ldb_msg_find_element(msg, "nTSecurityDescriptor");
352	objectclass_element = ldb_msg_find_element(msg, "objectClass");
353	objectclass = get_last_structural_class(schema, objectclass_element);
354
355	if (!objectclass) {
356		ldb_asprintf_errstring(ldb, "No last structural objectclass found on %s", ldb_dn_get_linearized(msg->dn));
357		return LDB_ERR_OPERATIONS_ERROR;
358	}
359
360	if (sd_element)
361		sd_val = &sd_element->values[0];
362	/* NC's have no parent */
363	if ((ldb_dn_compare(msg->dn, (ldb_get_schema_basedn(ldb))) == 0) ||
364	    (ldb_dn_compare(msg->dn, (ldb_get_config_basedn(ldb))) == 0) ||
365	    (ldb_dn_compare(msg->dn, (ldb_get_root_basedn(ldb))) == 0)) {
366		parentsd_val = NULL;
367	} else if (ac->search_res != NULL){
368		parentsd_val = ldb_msg_find_ldb_val(ac->search_res->message, "nTSecurityDescriptor");
369	}
370
371	/* get the parent descriptor and the one provided. If not provided, get the default.*/
372	/* convert to security descriptor and calculate */
373	sd = get_new_descriptor(ac->module, msg->dn, mem_ctx, objectclass,
374			parentsd_val, sd_val);
375	if (sd_val) {
376		ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
377	}
378
379	if (sd) {
380		ret = ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd);
381		if (ret != LDB_SUCCESS) {
382			return ret;
383		}
384	}
385
386	talloc_free(mem_ctx);
387	ret = ldb_msg_sanity_check(ldb, msg);
388
389	if (ret != LDB_SUCCESS) {
390		ldb_asprintf_errstring(ldb, "No last structural objectclass found on %s", ldb_dn_get_linearized(msg->dn));
391		return ret;
392	}
393
394	ret = ldb_build_add_req(&add_req, ldb, ac,
395				msg,
396				ac->req->controls,
397				ac, descriptor_op_callback,
398				ac->req);
399	if (ret != LDB_SUCCESS) {
400		return ret;
401	}
402
403	/* perform the add */
404	return ldb_next_request(ac->module, add_req);
405}
406
407static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
408{
409	struct ldb_context *ldb;
410	struct ldb_request *search_req;
411	struct descriptor_context *ac;
412	struct ldb_dn *parent_dn;
413	int ret;
414	struct descriptor_data *data;
415	static const char * const descr_attrs[] = { "nTSecurityDescriptor", NULL };
416
417	data = talloc_get_type(ldb_module_get_private(module), struct descriptor_data);
418	ldb = ldb_module_get_ctx(module);
419
420	ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_add\n");
421
422	if (ldb_dn_is_special(req->op.add.message->dn)) {
423		return ldb_next_request(module, req);
424	}
425
426	ac = descriptor_init_context(module, req);
427	if (ac == NULL) {
428		return LDB_ERR_OPERATIONS_ERROR;
429	}
430
431	/* If there isn't a parent, just go on to the add processing */
432	if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
433		return descriptor_do_add(ac);
434	}
435
436	/* get copy of parent DN */
437	parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
438	if (parent_dn == NULL) {
439		ldb_oom(ldb);
440		return LDB_ERR_OPERATIONS_ERROR;
441	}
442
443	ret = ldb_build_search_req(&search_req, ldb,
444				   ac, parent_dn, LDB_SCOPE_BASE,
445				   "(objectClass=*)", descr_attrs,
446				   NULL,
447				   ac, get_search_callback,
448				   req);
449	if (ret != LDB_SUCCESS) {
450		return ret;
451	}
452	talloc_steal(search_req, parent_dn);
453
454	ac->step_fn = descriptor_do_add;
455
456	return ldb_next_request(ac->module, search_req);
457}
458/* TODO */
459static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
460{
461	struct ldb_context *ldb = ldb_module_get_ctx(module);
462	ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_modify\n");
463	return ldb_next_request(module, req);
464}
465/* TODO */
466static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
467{
468	struct ldb_context *ldb = ldb_module_get_ctx(module);
469	ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_rename\n");
470	return ldb_next_request(module, req);
471}
472
473static int descriptor_init(struct ldb_module *module)
474{
475	struct ldb_context *ldb;
476	struct descriptor_data *data;
477
478	ldb = ldb_module_get_ctx(module);
479	data = talloc(module, struct descriptor_data);
480	if (data == NULL) {
481		ldb_oom(ldb);
482		return LDB_ERR_OPERATIONS_ERROR;
483	}
484
485	ldb_module_set_private(module, data);
486	return ldb_next_init(module);
487}
488
489
490_PUBLIC_ const struct ldb_module_ops ldb_descriptor_module_ops = {
491	.name		   = "descriptor",
492	.add           = descriptor_add,
493	.modify        = descriptor_modify,
494	.rename        = descriptor_rename,
495	.init_context  = descriptor_init
496};
497
498
499