4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5 Copyright (C) Simo Sorce 2004-2008
6 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
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.
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.
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/>.
25 * Component: ldb samldb module
27 * Description: add embedded user/group creation functionality
33 #include "libcli/ldap/ldap_ndr.h"
34 #include "ldb_module.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
37 #include "libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
39 #include "../lib/util/util_ldb.h"
41 #include "param/param.h"
45 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
48 struct samldb_step *next;
53 struct ldb_module *module;
54 struct ldb_request *req;
56 /* used for add operations */
59 /* the resulting message */
60 struct ldb_message *msg;
62 /* holds the entry SID */
65 /* holds a generic dn */
68 /* used in conjunction with "sid" in "samldb_dn_from_sid" */
69 struct ldb_dn *res_dn;
71 /* all the async steps necessary to complete the operation */
72 struct samldb_step *steps;
73 struct samldb_step *curstep;
75 /* If someone set an ares to forward controls and response back to the caller */
76 struct ldb_reply *ares;
79 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
80 struct ldb_request *req)
82 struct ldb_context *ldb;
83 struct samldb_ctx *ac;
85 ldb = ldb_module_get_ctx(module);
87 ac = talloc_zero(req, struct samldb_ctx);
99 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
101 struct samldb_step *step, *stepper;
103 step = talloc_zero(ac, struct samldb_step);
105 return LDB_ERR_OPERATIONS_ERROR;
110 if (ac->steps == NULL) {
114 if (ac->curstep == NULL)
115 return LDB_ERR_OPERATIONS_ERROR;
116 for (stepper = ac->curstep; stepper->next != NULL;
117 stepper = stepper->next);
118 stepper->next = step;
124 static int samldb_first_step(struct samldb_ctx *ac)
126 if (ac->steps == NULL) {
127 return LDB_ERR_OPERATIONS_ERROR;
130 ac->curstep = ac->steps;
131 return ac->curstep->fn(ac);
134 static int samldb_next_step(struct samldb_ctx *ac)
136 if (ac->curstep->next) {
137 ac->curstep = ac->curstep->next;
138 return ac->curstep->fn(ac);
141 /* we exit the samldb module here */
142 /* If someone set an ares to forward controls and response back to the caller, use them */
144 return ldb_module_done(ac->req, ac->ares->controls,
145 ac->ares->response, LDB_SUCCESS);
147 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
151 static int samldb_generate_samAccountName(struct ldb_message *msg)
155 /* Format: $000000-000000000000 */
157 name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
158 (unsigned int)generate_random(),
159 (unsigned int)generate_random(),
160 (unsigned int)generate_random());
162 return LDB_ERR_OPERATIONS_ERROR;
164 return ldb_msg_add_steal_string(msg, "samAccountName", name);
168 * samldb_check_samAccountName (async)
171 static int samldb_check_samAccountName_callback(struct ldb_request *req,
172 struct ldb_reply *ares)
174 struct samldb_ctx *ac;
177 ac = talloc_get_type(req->context, struct samldb_ctx);
179 if (ares->error != LDB_SUCCESS) {
180 return ldb_module_done(ac->req, ares->controls,
181 ares->response, ares->error);
184 switch (ares->type) {
185 case LDB_REPLY_ENTRY:
186 /* if we get an entry it means this samAccountName
188 return ldb_module_done(ac->req, NULL, NULL,
189 LDB_ERR_ENTRY_ALREADY_EXISTS);
191 case LDB_REPLY_REFERRAL:
198 /* not found, go on */
200 ret = samldb_next_step(ac);
204 if (ret != LDB_SUCCESS) {
205 return ldb_module_done(ac->req, NULL, NULL, ret);
211 static int samldb_check_samAccountName(struct samldb_ctx *ac)
213 struct ldb_context *ldb;
214 struct ldb_request *req;
219 ldb = ldb_module_get_ctx(ac->module);
221 if (ldb_msg_find_element(ac->msg, "samAccountName") == NULL) {
222 ret = samldb_generate_samAccountName(ac->msg);
223 if (ret != LDB_SUCCESS) {
228 name = ldb_msg_find_attr_as_string(ac->msg, "samAccountName", NULL);
230 return LDB_ERR_OPERATIONS_ERROR;
232 filter = talloc_asprintf(ac, "samAccountName=%s",
233 ldb_binary_encode_string(ac, name));
234 if (filter == NULL) {
235 return LDB_ERR_OPERATIONS_ERROR;
238 ret = ldb_build_search_req(&req, ldb, ac,
239 ldb_get_default_basedn(ldb),
243 ac, samldb_check_samAccountName_callback,
246 if (ret != LDB_SUCCESS) {
249 return ldb_next_request(ac->module, req);
253 static int samldb_check_samAccountType(struct samldb_ctx *ac)
255 struct ldb_context *ldb;
256 unsigned int account_type;
257 unsigned int group_type;
261 ldb = ldb_module_get_ctx(ac->module);
263 /* make sure sAMAccountType is not specified */
264 if (ldb_msg_find_element(ac->msg, "sAMAccountType") != NULL) {
265 ldb_asprintf_errstring(ldb,
266 "sAMAccountType must not be specified!");
267 return LDB_ERR_UNWILLING_TO_PERFORM;
270 if (strcmp("user", ac->type) == 0) {
271 uac = samdb_result_uint(ac->msg, "userAccountControl", 0);
273 ldb_asprintf_errstring(ldb,
274 "userAccountControl invalid!");
275 return LDB_ERR_UNWILLING_TO_PERFORM;
277 account_type = ds_uf2atype(uac);
278 ret = samdb_msg_add_uint(ldb,
282 if (ret != LDB_SUCCESS) {
287 if (strcmp("group", ac->type) == 0) {
289 group_type = samdb_result_uint(ac->msg, "groupType", 0);
290 if (group_type == 0) {
291 ldb_asprintf_errstring(ldb,
292 "groupType invalid!\n");
293 return LDB_ERR_UNWILLING_TO_PERFORM;
295 account_type = ds_gtype2atype(group_type);
296 ret = samdb_msg_add_uint(ldb,
300 if (ret != LDB_SUCCESS) {
306 return samldb_next_step(ac);
309 static bool samldb_msg_add_sid(struct ldb_message *msg,
311 const struct dom_sid *sid)
314 enum ndr_err_code ndr_err;
316 ndr_err = ndr_push_struct_blob(&v, msg, sid,
317 (ndr_push_flags_fn_t)ndr_push_dom_sid);
318 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
321 return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
325 /* allocate a SID using our RID Set */
326 static int samldb_allocate_sid(struct samldb_ctx *ac)
330 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
332 ret = ridalloc_allocate_rid(ac->module, &rid);
333 if (ret != LDB_SUCCESS) {
337 ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
338 if (ac->sid == NULL) {
339 ldb_module_oom(ac->module);
340 return LDB_ERR_OPERATIONS_ERROR;
343 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
344 return LDB_ERR_OPERATIONS_ERROR;
347 return samldb_next_step(ac);
351 * samldb_dn_from_sid (async)
354 static int samldb_dn_from_sid(struct samldb_ctx *ac);
356 static int samldb_dn_from_sid_callback(struct ldb_request *req,
357 struct ldb_reply *ares)
359 struct ldb_context *ldb;
360 struct samldb_ctx *ac;
363 ac = talloc_get_type(req->context, struct samldb_ctx);
364 ldb = ldb_module_get_ctx(ac->module);
367 ret = LDB_ERR_OPERATIONS_ERROR;
370 if (ares->error != LDB_SUCCESS) {
371 return ldb_module_done(ac->req, ares->controls,
372 ares->response, ares->error);
375 switch (ares->type) {
376 case LDB_REPLY_ENTRY:
378 if (ac->res_dn != NULL) {
380 ldb_set_errstring(ldb,
381 "Invalid number of results while searching "
382 "for domain objects!");
383 ret = LDB_ERR_OPERATIONS_ERROR;
386 ac->res_dn = ldb_dn_copy(ac, ares->message->dn);
392 case LDB_REPLY_REFERRAL:
401 /* found or not found, go on */
402 ret = samldb_next_step(ac);
407 if (ret != LDB_SUCCESS) {
408 return ldb_module_done(ac->req, NULL, NULL, ret);
414 /* Finds the DN "res_dn" of an object with a given SID "sid" */
415 static int samldb_dn_from_sid(struct samldb_ctx *ac)
417 struct ldb_context *ldb;
418 static const char * const attrs[] = { NULL };
419 struct ldb_request *req;
423 ldb = ldb_module_get_ctx(ac->module);
426 return LDB_ERR_OPERATIONS_ERROR;
428 filter = talloc_asprintf(ac, "(objectSid=%s)",
429 ldap_encode_ndr_dom_sid(ac, ac->sid));
431 return LDB_ERR_OPERATIONS_ERROR;
433 ret = ldb_build_search_req(&req, ldb, ac,
434 ldb_get_default_basedn(ldb),
438 ac, samldb_dn_from_sid_callback,
440 if (ret != LDB_SUCCESS)
443 return ldb_next_request(ac->module, req);
447 static int samldb_check_primaryGroupID_1(struct samldb_ctx *ac)
449 struct ldb_context *ldb;
452 ldb = ldb_module_get_ctx(ac->module);
454 rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
455 ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
457 return LDB_ERR_OPERATIONS_ERROR;
460 return samldb_next_step(ac);
463 static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
465 if (ac->res_dn == NULL) {
466 struct ldb_context *ldb;
467 ldb = ldb_module_get_ctx(ac->module);
468 ldb_asprintf_errstring(ldb,
469 "Failed to find group sid %s!",
470 dom_sid_string(ac->sid, ac->sid));
471 return LDB_ERR_UNWILLING_TO_PERFORM;
474 return samldb_next_step(ac);
479 * samldb_set_defaultObjectCategory_callback (async)
482 static int samldb_set_defaultObjectCategory_callback(struct ldb_request *req,
483 struct ldb_reply *ares)
485 struct ldb_context *ldb;
486 struct samldb_ctx *ac;
489 ac = talloc_get_type(req->context, struct samldb_ctx);
490 ldb = ldb_module_get_ctx(ac->module);
493 ret = LDB_ERR_OPERATIONS_ERROR;
497 if (ares->type == LDB_REPLY_REFERRAL) {
498 return ldb_module_send_referral(ac->req, ares->referral);
501 if (ares->error != LDB_SUCCESS) {
502 return ldb_module_done(ac->req, ares->controls,
503 ares->response, ares->error);
505 if (ares->type != LDB_REPLY_DONE) {
506 ldb_set_errstring(ldb,
507 "Invalid reply type!");
508 ret = LDB_ERR_OPERATIONS_ERROR;
512 ret = samldb_next_step(ac);
515 if (ret != LDB_SUCCESS) {
516 return ldb_module_done(ac->req, NULL, NULL, ret);
522 static int samldb_set_defaultObjectCategory(struct samldb_ctx *ac)
524 struct ldb_context *ldb;
525 struct ldb_message *msg;
526 struct ldb_request *req;
529 ldb = ldb_module_get_ctx(ac->module);
531 /* (Re)set the default object category to have it set to the DN in the
533 msg = ldb_msg_new(ac);
534 msg->dn = ac->msg->dn;
535 ldb_msg_add_empty(msg, "defaultObjectCategory",
536 LDB_FLAG_MOD_REPLACE, NULL);
537 ldb_msg_add_steal_string(msg, "defaultObjectCategory",
538 ldb_dn_alloc_linearized(msg, ac->dn));
540 ret = ldb_build_mod_req(&req, ldb, ac,
543 samldb_set_defaultObjectCategory_callback,
545 if (ret != LDB_SUCCESS) {
550 return ldb_next_request(ac->module, req);
554 * samldb_find_for_defaultObjectCategory (async)
557 static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req,
558 struct ldb_reply *ares)
560 struct ldb_context *ldb;
561 struct samldb_ctx *ac;
564 ac = talloc_get_type(req->context, struct samldb_ctx);
565 ldb = ldb_module_get_ctx(ac->module);
568 ret = LDB_ERR_OPERATIONS_ERROR;
571 if (ares->error != LDB_SUCCESS) {
572 if (ares->error == LDB_ERR_NO_SUCH_OBJECT) {
573 if (ldb_request_get_control(ac->req,
574 LDB_CONTROL_RELAX_OID) != NULL) {
575 /* Don't be pricky when the DN doesn't exist */
576 /* if we have the RELAX control specified */
577 ac->dn = req->op.search.base;
578 return samldb_next_step(ac);
580 ldb_set_errstring(ldb,
581 "samldb_find_defaultObjectCategory: "
582 "Invalid DN for 'defaultObjectCategory'!");
583 ares->error = LDB_ERR_CONSTRAINT_VIOLATION;
587 return ldb_module_done(ac->req, ares->controls,
588 ares->response, ares->error);
591 switch (ares->type) {
592 case LDB_REPLY_ENTRY:
593 ac->dn = talloc_steal(ac, ares->message->dn);
598 case LDB_REPLY_REFERRAL:
607 if (ac->dn != NULL) {
608 /* when found go on */
609 ret = samldb_next_step(ac);
611 ret = LDB_ERR_OPERATIONS_ERROR;
617 if (ret != LDB_SUCCESS) {
618 return ldb_module_done(ac->req, NULL, NULL, ret);
624 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
626 struct ldb_context *ldb;
627 struct ldb_request *req;
628 static const char *no_attrs[] = { NULL };
630 const struct ldb_val *val;
631 struct ldb_dn *def_obj_cat_dn;
633 ldb = ldb_module_get_ctx(ac->module);
637 val = ldb_msg_find_ldb_val(ac->msg, "defaultObjectCategory");
639 /* "defaultObjectCategory" has been set by the caller. Do some
640 * checks for consistency.
641 * NOTE: The real constraint check (that 'defaultObjectCategory'
642 * is the DN of the new objectclass or any parent of it) is
644 * For now we say that 'defaultObjectCategory' is valid if it
645 * exists and it is of objectclass "classSchema". */
646 def_obj_cat_dn = ldb_dn_from_ldb_val(ac, ldb, val);
647 if (def_obj_cat_dn == NULL) {
648 ldb_set_errstring(ldb,
649 "samldb_find_defaultObjectCategory: Invalid DN "
650 "for 'defaultObjectCategory'!");
651 return LDB_ERR_CONSTRAINT_VIOLATION;
654 /* "defaultObjectCategory" has not been set by the caller. Use
655 * the entry DN for it. */
656 def_obj_cat_dn = ac->msg->dn;
659 ret = ldb_build_search_req(&req, ldb, ac,
660 def_obj_cat_dn, LDB_SCOPE_BASE,
661 "objectClass=classSchema", no_attrs,
663 ac, samldb_find_for_defaultObjectCategory_callback,
665 if (ret != LDB_SUCCESS) {
669 ret = dsdb_request_add_controls(req,
670 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
671 if (ret != LDB_SUCCESS) {
675 return ldb_next_request(ac->module, req);
679 * msDS-IntId attributeSchema attribute handling
680 * during LDB_ADD request processing
682 static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
687 uint32_t system_flags;
688 struct ldb_context *ldb;
689 struct ldb_result *ldb_res;
690 struct ldb_dn *schema_dn;
692 ldb = ldb_module_get_ctx(ac->module);
693 schema_dn = ldb_get_schema_basedn(ldb);
695 /* replicated update should always go through */
696 if (ldb_request_get_control(ac->req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
700 /* msDS-IntId is handled by system and should never be
701 * passed by clients */
702 if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
703 return LDB_ERR_UNWILLING_TO_PERFORM;
706 /* do not generate msDS-IntId if Relax control is passed */
707 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
711 /* check Functional Level */
712 if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
716 /* check systemFlags for SCHEMA_BASE_OBJECT flag */
717 system_flags = ldb_msg_find_attr_as_uint(ac->msg, "systemFlags", 0);
718 if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
722 /* Generate new value for msDs-IntId
723 * Value should be in 0x80000000..0xBFFFFFFF range */
724 msds_intid = generate_random() % 0X3FFFFFFF;
725 msds_intid += 0x80000000;
727 /* probe id values until unique one is found */
730 if (msds_intid > 0xBFFFFFFF) {
731 msds_intid = 0x80000001;
734 ret = dsdb_module_search(ac->module, ac,
736 schema_dn, LDB_SCOPE_ONELEVEL, NULL, 0,
737 "(msDS-IntId=%d)", msds_intid);
738 if (ret != LDB_SUCCESS) {
739 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
740 __location__": Searching for msDS-IntId=%d failed - %s\n",
743 return LDB_ERR_OPERATIONS_ERROR;
745 id_exists = (ldb_res->count > 0);
747 talloc_free(ldb_res);
750 return ldb_msg_add_fmt(ac->msg, "msDS-IntId", "%d", msds_intid);
755 * samldb_add_entry (async)
758 static int samldb_add_entry_callback(struct ldb_request *req,
759 struct ldb_reply *ares)
761 struct ldb_context *ldb;
762 struct samldb_ctx *ac;
765 ac = talloc_get_type(req->context, struct samldb_ctx);
766 ldb = ldb_module_get_ctx(ac->module);
769 return ldb_module_done(ac->req, NULL, NULL,
770 LDB_ERR_OPERATIONS_ERROR);
773 if (ares->type == LDB_REPLY_REFERRAL) {
774 return ldb_module_send_referral(ac->req, ares->referral);
777 if (ares->error != LDB_SUCCESS) {
778 return ldb_module_done(ac->req, ares->controls,
779 ares->response, ares->error);
781 if (ares->type != LDB_REPLY_DONE) {
782 ldb_set_errstring(ldb,
783 "Invalid reply type!\n");
784 return ldb_module_done(ac->req, NULL, NULL,
785 LDB_ERR_OPERATIONS_ERROR);
788 /* The caller may wish to get controls back from the add */
789 ac->ares = talloc_steal(ac, ares);
791 ret = samldb_next_step(ac);
792 if (ret != LDB_SUCCESS) {
793 return ldb_module_done(ac->req, NULL, NULL, ret);
798 static int samldb_add_entry(struct samldb_ctx *ac)
800 struct ldb_context *ldb;
801 struct ldb_request *req;
804 ldb = ldb_module_get_ctx(ac->module);
806 ret = ldb_build_add_req(&req, ldb, ac,
809 ac, samldb_add_entry_callback,
811 if (ret != LDB_SUCCESS) {
815 return ldb_next_request(ac->module, req);
819 * return true if msg carries an attributeSchema that is intended to be RODC
820 * filtered but is also a system-critical attribute.
822 static bool check_rodc_critical_attribute(struct ldb_message *msg)
824 uint32_t schemaFlagsEx, searchFlags, rodc_filtered_flags;
826 schemaFlagsEx = ldb_msg_find_attr_as_uint(msg, "schemaFlagsEx", 0);
827 searchFlags = ldb_msg_find_attr_as_uint(msg, "searchFlags", 0);
828 rodc_filtered_flags = (SEARCH_FLAG_RODC_ATTRIBUTE | SEARCH_FLAG_CONFIDENTIAL);
830 if ((schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) &&
831 ((searchFlags & rodc_filtered_flags) == rodc_filtered_flags)) {
839 static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
841 struct ldb_context *ldb;
842 struct loadparm_context *lp_ctx;
843 enum sid_generator sid_generator;
846 ldb = ldb_module_get_ctx(ac->module);
848 /* Add informations for the different account types */
850 if (strcmp(ac->type, "user") == 0) {
851 ret = samdb_find_or_add_attribute(ldb, ac->msg,
852 "userAccountControl", "546");
853 if (ret != LDB_SUCCESS) return ret;
854 ret = samdb_find_or_add_attribute(ldb, ac->msg,
856 if (ret != LDB_SUCCESS) return ret;
857 ret = samdb_find_or_add_attribute(ldb, ac->msg,
859 if (ret != LDB_SUCCESS) return ret;
860 ret = samdb_find_or_add_attribute(ldb, ac->msg,
862 if (ret != LDB_SUCCESS) return ret;
863 ret = samdb_find_or_add_attribute(ldb, ac->msg,
864 "badPasswordTime", "0");
865 if (ret != LDB_SUCCESS) return ret;
866 ret = samdb_find_or_add_attribute(ldb, ac->msg,
868 if (ret != LDB_SUCCESS) return ret;
869 ret = samdb_find_or_add_attribute(ldb, ac->msg,
871 if (ret != LDB_SUCCESS) return ret;
872 ret = samdb_find_or_add_attribute(ldb, ac->msg,
874 if (ret != LDB_SUCCESS) return ret;
875 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
876 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
877 "primaryGroupID", DOMAIN_RID_USERS);
878 if (ret != LDB_SUCCESS) return ret;
880 ret = samdb_find_or_add_attribute(ldb, ac->msg,
881 "accountExpires", "9223372036854775807");
882 if (ret != LDB_SUCCESS) return ret;
883 ret = samdb_find_or_add_attribute(ldb, ac->msg,
885 if (ret != LDB_SUCCESS) return ret;
886 } else if (strcmp(ac->type, "group") == 0) {
887 ret = samdb_find_or_add_attribute(ldb, ac->msg,
888 "groupType", "-2147483646");
889 if (ret != LDB_SUCCESS) return ret;
890 } else if (strcmp(ac->type, "classSchema") == 0) {
891 const struct ldb_val *rdn_value;
893 ret = samdb_find_or_add_attribute(ldb, ac->msg,
895 if (ret != LDB_SUCCESS) return ret;
897 /* do not allow to mark an attributeSchema as RODC filtered if it
898 * is system-critical */
899 if (check_rodc_critical_attribute(ac->msg)) {
900 ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
901 ldb_dn_get_linearized(ac->msg->dn));
902 return LDB_ERR_UNWILLING_TO_PERFORM;
906 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
907 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
908 /* the RDN has prefix "CN" */
909 ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
910 samdb_cn_to_lDAPDisplayName(ac,
911 (const char *) rdn_value->data));
912 if (ret != LDB_SUCCESS) {
918 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
921 guid = GUID_random();
922 ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
923 if (ret != LDB_SUCCESS) {
929 ret = samldb_add_step(ac, samldb_add_entry);
930 if (ret != LDB_SUCCESS) return ret;
932 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
933 if (ret != LDB_SUCCESS) return ret;
935 ret = samldb_add_step(ac, samldb_set_defaultObjectCategory);
936 if (ret != LDB_SUCCESS) return ret;
938 return samldb_first_step(ac);
939 } else if (strcmp(ac->type, "attributeSchema") == 0) {
940 const struct ldb_val *rdn_value;
941 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
942 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
943 /* the RDN has prefix "CN" */
944 ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
945 samdb_cn_to_lDAPDisplayName(ac,
946 (const char *) rdn_value->data));
947 if (ret != LDB_SUCCESS) {
953 /* do not allow to mark an attributeSchema as RODC filtered if it
954 * is system-critical */
955 if (check_rodc_critical_attribute(ac->msg)) {
956 ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical attribute with RODC filtering",
957 ldb_dn_get_linearized(ac->msg->dn));
958 return LDB_ERR_UNWILLING_TO_PERFORM;
961 ret = samdb_find_or_add_attribute(ldb, ac->msg,
962 "isSingleValued", "FALSE");
963 if (ret != LDB_SUCCESS) return ret;
965 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
968 guid = GUID_random();
969 ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
970 if (ret != LDB_SUCCESS) {
976 /* handle msDS-IntID attribute */
977 ret = samldb_add_handle_msDS_IntId(ac);
978 if (ret != LDB_SUCCESS) return ret;
980 ret = samldb_add_step(ac, samldb_add_entry);
981 if (ret != LDB_SUCCESS) return ret;
983 return samldb_first_step(ac);
985 ldb_asprintf_errstring(ldb,
986 "Invalid entry type!");
987 return LDB_ERR_OPERATIONS_ERROR;
990 /* check if we have a valid samAccountName */
991 ret = samldb_add_step(ac, samldb_check_samAccountName);
992 if (ret != LDB_SUCCESS) return ret;
994 /* check account_type/group_type */
995 ret = samldb_add_step(ac, samldb_check_samAccountType);
996 if (ret != LDB_SUCCESS) return ret;
998 /* check if we have a valid primary group ID */
999 if (strcmp(ac->type, "user") == 0) {
1000 ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
1001 if (ret != LDB_SUCCESS) return ret;
1002 ret = samldb_add_step(ac, samldb_dn_from_sid);
1003 if (ret != LDB_SUCCESS) return ret;
1004 ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
1005 if (ret != LDB_SUCCESS) return ret;
1008 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1009 struct loadparm_context);
1011 /* don't allow objectSID to be specified without the RELAX control */
1012 ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1013 if (ac->sid && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
1014 !dsdb_module_am_system(ac->module)) {
1015 ldb_asprintf_errstring(ldb, "No SID may be specified in user/group creation for %s",
1016 ldb_dn_get_linearized(ac->msg->dn));
1017 return LDB_ERR_UNWILLING_TO_PERFORM;
1021 sid_generator = lp_sid_generator(lp_ctx);
1022 if (sid_generator == SID_GENERATOR_INTERNAL) {
1023 ret = samldb_add_step(ac, samldb_allocate_sid);
1024 if (ret != LDB_SUCCESS) return ret;
1028 /* finally proceed with adding the entry */
1029 ret = samldb_add_step(ac, samldb_add_entry);
1030 if (ret != LDB_SUCCESS) return ret;
1032 return samldb_first_step(ac);
1035 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1037 struct ldb_context *ldb;
1040 ldb = ldb_module_get_ctx(ac->module);
1042 ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1043 if (ac->sid == NULL) {
1044 ac->sid = dom_sid_parse_talloc(ac->msg,
1045 (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1047 ldb_set_errstring(ldb,
1048 "No valid SID found in "
1049 "ForeignSecurityPrincipal CN!");
1051 return LDB_ERR_CONSTRAINT_VIOLATION;
1053 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1055 return LDB_ERR_OPERATIONS_ERROR;
1059 /* finally proceed with adding the entry */
1060 ret = samldb_add_step(ac, samldb_add_entry);
1061 if (ret != LDB_SUCCESS) return ret;
1063 return samldb_first_step(ac);
1066 static int samldb_schema_info_update(struct samldb_ctx *ac)
1069 struct ldb_context *ldb;
1070 struct dsdb_schema *schema;
1072 /* replicated update should always go through */
1073 if (ldb_request_get_control(ac->req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1077 /* do not update schemaInfo during provisioning */
1078 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1082 ldb = ldb_module_get_ctx(ac->module);
1083 schema = dsdb_get_schema(ldb, NULL);
1085 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1086 "samldb_schema_info_update: no dsdb_schema loaded");
1087 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1088 return LDB_ERR_OPERATIONS_ERROR;
1091 werr = dsdb_module_schema_info_update(ac->module, schema, 0);
1092 if (!W_ERROR_IS_OK(werr)) {
1093 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1094 "samldb_schema_info_update: "
1095 "dsdb_module_schema_info_update failed with %s",
1097 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1098 return LDB_ERR_OPERATIONS_ERROR;
1105 static int samldb_prim_group_change(struct samldb_ctx *ac)
1107 struct ldb_context *ldb;
1108 const char * attrs[] = { "primaryGroupID", "memberOf", NULL };
1109 struct ldb_result *res;
1110 struct ldb_message_element *el;
1111 struct ldb_message *msg;
1113 struct dom_sid *sid;
1114 struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1117 ldb = ldb_module_get_ctx(ac->module);
1119 /* Fetch informations from the existing object */
1121 ret = ldb_search(ldb, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1123 if (ret != LDB_SUCCESS) {
1127 /* Finds out the DN of the old primary group */
1129 rid = samdb_result_uint(res->msgs[0], "primaryGroupID", (uint32_t) -1);
1130 if (rid == (uint32_t) -1) {
1131 /* User objects do always have a mandatory "primaryGroupID"
1132 * attribute. If this doesn't exist then the object is of the
1133 * wrong type. This is the exact Windows error code */
1134 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1137 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1139 return LDB_ERR_OPERATIONS_ERROR;
1142 prev_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
1143 dom_sid_string(ac, sid));
1144 if (prev_prim_group_dn == NULL) {
1145 return LDB_ERR_OPERATIONS_ERROR;
1148 /* Finds out the DN of the new primary group */
1150 rid = samdb_result_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
1151 if (rid == (uint32_t) -1) {
1152 /* we aren't affected of any primary group change */
1156 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1158 return LDB_ERR_OPERATIONS_ERROR;
1161 new_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
1162 dom_sid_string(ac, sid));
1163 if (new_prim_group_dn == NULL) {
1164 /* Here we know if the specified new primary group candidate is
1166 return LDB_ERR_UNWILLING_TO_PERFORM;
1169 el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1170 ldb_dn_get_linearized(new_prim_group_dn));
1172 /* We need to be already a normal member of the new primary
1173 * group in order to be successful. */
1174 return LDB_ERR_UNWILLING_TO_PERFORM;
1177 /* Only update the "member" attributes when we really do have a change */
1178 if (ldb_dn_compare(new_prim_group_dn, prev_prim_group_dn) != 0) {
1179 /* Remove the "member" attribute on the new primary group */
1180 msg = talloc_zero(ac, struct ldb_message);
1181 msg->dn = new_prim_group_dn;
1183 ret = samdb_msg_add_delval(ldb, ac, msg, "member",
1184 ldb_dn_get_linearized(ac->msg->dn));
1185 if (ret != LDB_SUCCESS) {
1189 ret = dsdb_module_modify(ac->module, msg, 0);
1190 if (ret != LDB_SUCCESS) {
1194 /* Add a "member" attribute for the previous primary group */
1195 msg = talloc_zero(ac, struct ldb_message);
1196 msg->dn = prev_prim_group_dn;
1198 ret = samdb_msg_add_addval(ldb, ac, msg, "member",
1199 ldb_dn_get_linearized(ac->msg->dn));
1200 if (ret != LDB_SUCCESS) {
1204 ret = dsdb_module_modify(ac->module, msg, 0);
1205 if (ret != LDB_SUCCESS) {
1214 static int samldb_member_check(struct samldb_ctx *ac)
1216 struct ldb_context *ldb;
1217 struct ldb_message_element *el;
1218 struct ldb_dn *member_dn, *group_dn;
1219 uint32_t prim_group_rid;
1220 struct dom_sid *sid;
1223 ldb = ldb_module_get_ctx(ac->module);
1225 el = ldb_msg_find_element(ac->msg, "member");
1227 /* we aren't affected */
1231 for (i = 0; i < el->num_values; i++) {
1232 /* Denies to add "member"s to groups which are primary ones
1234 member_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[i]);
1235 if (!ldb_dn_validate(member_dn)) {
1236 return LDB_ERR_OPERATIONS_ERROR;
1239 prim_group_rid = samdb_search_uint(ldb, ac, (uint32_t) -1,
1240 member_dn, "primaryGroupID",
1242 if (prim_group_rid == (uint32_t) -1) {
1243 /* the member hasn't to be a user account -> therefore
1244 * no check needed in this case. */
1248 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1251 return LDB_ERR_OPERATIONS_ERROR;
1254 group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
1255 dom_sid_string(ac, sid));
1256 if (group_dn == NULL) {
1257 return LDB_ERR_OPERATIONS_ERROR;
1260 if (ldb_dn_compare(group_dn, ac->msg->dn) == 0) {
1261 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1269 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
1271 struct ldb_context *ldb;
1272 struct dom_sid *sid;
1277 ldb = ldb_module_get_ctx(ac->module);
1279 /* Finds out the SID/RID of the SAM object */
1280 sid = samdb_search_dom_sid(ldb, ac, ac->req->op.del.dn, "objectSID",
1283 /* No SID - it might not be a SAM object - therefore ok */
1286 status = dom_sid_split_rid(ac, sid, NULL, &rid);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 return LDB_ERR_OPERATIONS_ERROR;
1291 /* Special object (security principal?) */
1295 /* Deny delete requests from groups which are primary ones */
1296 count = samdb_search_count(ldb, NULL,
1297 "(&(primaryGroupID=%u)(objectClass=user))",
1300 return LDB_ERR_OPERATIONS_ERROR;
1303 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1311 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1313 struct ldb_context *ldb;
1314 struct samldb_ctx *ac;
1317 ldb = ldb_module_get_ctx(module);
1318 ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
1320 /* do not manipulate our control entries */
1321 if (ldb_dn_is_special(req->op.add.message->dn)) {
1322 return ldb_next_request(module, req);
1325 ac = samldb_ctx_init(module, req);
1327 return LDB_ERR_OPERATIONS_ERROR;
1330 /* build the new msg */
1331 ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
1334 ldb_debug(ldb, LDB_DEBUG_FATAL,
1335 "samldb_add: ldb_msg_copy failed!\n");
1336 return LDB_ERR_OPERATIONS_ERROR;
1339 if (samdb_find_attribute(ldb, ac->msg,
1340 "objectclass", "user") != NULL) {
1341 return samldb_fill_object(ac, "user");
1344 if (samdb_find_attribute(ldb, ac->msg,
1345 "objectclass", "group") != NULL) {
1346 return samldb_fill_object(ac, "group");
1349 /* perhaps a foreignSecurityPrincipal? */
1350 if (samdb_find_attribute(ldb, ac->msg,
1352 "foreignSecurityPrincipal") != NULL) {
1353 return samldb_fill_foreignSecurityPrincipal_object(ac);
1356 if (samdb_find_attribute(ldb, ac->msg,
1357 "objectclass", "classSchema") != NULL) {
1358 ret = samldb_schema_info_update(ac);
1359 if (ret != LDB_SUCCESS) {
1364 return samldb_fill_object(ac, "classSchema");
1367 if (samdb_find_attribute(ldb, ac->msg,
1368 "objectclass", "attributeSchema") != NULL) {
1369 ret = samldb_schema_info_update(ac);
1370 if (ret != LDB_SUCCESS) {
1375 return samldb_fill_object(ac, "attributeSchema");
1380 /* nothing matched, go on */
1381 return ldb_next_request(module, req);
1385 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
1387 struct ldb_context *ldb;
1388 struct ldb_message *msg;
1389 struct ldb_message_element *el, *el2;
1391 uint32_t account_type;
1393 if (ldb_dn_is_special(req->op.mod.message->dn)) {
1394 /* do not manipulate our control entries */
1395 return ldb_next_request(module, req);
1398 ldb = ldb_module_get_ctx(module);
1400 if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
1401 ldb_asprintf_errstring(ldb,
1402 "sAMAccountType must not be specified!");
1403 return LDB_ERR_UNWILLING_TO_PERFORM;
1406 /* msDS-IntId is not allowed to be modified
1407 * except when modification comes from replication */
1408 if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
1409 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1410 return LDB_ERR_CONSTRAINT_VIOLATION;
1414 /* TODO: do not modify original request, create a new one */
1416 el = ldb_msg_find_element(req->op.mod.message, "groupType");
1417 if (el && (el->flags == LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1418 uint32_t group_type;
1420 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1421 req->op.mod.message);
1423 group_type = strtoul((const char *)el->values[0].data, NULL, 0);
1424 account_type = ds_gtype2atype(group_type);
1425 ret = samdb_msg_add_uint(ldb, msg, msg,
1428 if (ret != LDB_SUCCESS) {
1431 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1432 el2->flags = LDB_FLAG_MOD_REPLACE;
1434 if (el && (el->flags == LDB_FLAG_MOD_DELETE)) {
1435 return LDB_ERR_UNWILLING_TO_PERFORM;
1438 el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
1439 if (el && (el->flags == LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1440 struct samldb_ctx *ac;
1442 ac = samldb_ctx_init(module, req);
1444 return LDB_ERR_OPERATIONS_ERROR;
1446 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
1447 req->op.mod.message);
1449 ret = samldb_prim_group_change(ac);
1450 if (ret != LDB_SUCCESS) {
1454 if (el && (el->flags == LDB_FLAG_MOD_DELETE)) {
1455 return LDB_ERR_UNWILLING_TO_PERFORM;
1458 el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
1459 if (el && (el->flags == LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1460 uint32_t user_account_control;
1462 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1463 req->op.mod.message);
1465 user_account_control = strtoul((const char *)el->values[0].data,
1467 account_type = ds_uf2atype(user_account_control);
1468 ret = samdb_msg_add_uint(ldb, msg, msg,
1471 if (ret != LDB_SUCCESS) {
1474 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1475 el2->flags = LDB_FLAG_MOD_REPLACE;
1477 if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
1478 ret = samdb_msg_add_string(ldb, msg, msg,
1479 "isCriticalSystemObject", "TRUE");
1480 if (ret != LDB_SUCCESS) {
1483 el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
1484 el2->flags = LDB_FLAG_MOD_REPLACE;
1486 /* DCs have primaryGroupID of DOMAIN_RID_DCS */
1487 if (!ldb_msg_find_element(msg, "primaryGroupID")) {
1488 ret = samdb_msg_add_uint(ldb, msg, msg,
1489 "primaryGroupID", DOMAIN_RID_DCS);
1490 if (ret != LDB_SUCCESS) {
1493 el2 = ldb_msg_find_element(msg, "primaryGroupID");
1494 el2->flags = LDB_FLAG_MOD_REPLACE;
1498 if (el && (el->flags == LDB_FLAG_MOD_DELETE)) {
1499 return LDB_ERR_UNWILLING_TO_PERFORM;
1502 el = ldb_msg_find_element(req->op.mod.message, "member");
1503 if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1504 struct samldb_ctx *ac;
1506 ac = samldb_ctx_init(module, req);
1508 return LDB_ERR_OPERATIONS_ERROR;
1510 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
1511 req->op.mod.message);
1513 ret = samldb_member_check(ac);
1514 if (ret != LDB_SUCCESS) {
1519 return ldb_next_request(module, req);
1523 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
1525 struct samldb_ctx *ac;
1528 if (ldb_dn_is_special(req->op.del.dn)) {
1529 /* do not manipulate our control entries */
1530 return ldb_next_request(module, req);
1533 ac = samldb_ctx_init(module, req);
1535 return LDB_ERR_OPERATIONS_ERROR;
1537 ret = samldb_prim_group_users_check(ac);
1538 if (ret != LDB_SUCCESS) {
1542 return ldb_next_request(module, req);
1545 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
1547 struct ldb_context *ldb = ldb_module_get_ctx(module);
1548 struct dsdb_fsmo_extended_op *exop;
1551 exop = talloc_get_type(req->op.extended.data, struct dsdb_fsmo_extended_op);
1553 ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_extended_allocate_rid_pool: invalid extended data\n");
1554 return LDB_ERR_PROTOCOL_ERROR;
1557 ret = ridalloc_allocate_rid_pool_fsmo(module, exop);
1558 if (ret != LDB_SUCCESS) {
1562 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1565 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
1567 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
1568 return samldb_extended_allocate_rid_pool(module, req);
1571 return ldb_next_request(module, req);
1575 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
1578 .modify = samldb_modify,
1579 .del = samldb_delete,
1580 .extended = samldb_extended