4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2014
5 Copyright (C) Simo Sorce 2004-2008
6 Copyright (C) Matthias Dieter Wallnöfer 2009-2011
7 Copyright (C) Matthieu Patou 2012
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 * Component: ldb samldb module
28 * Description: various internal DSDB triggers - most for SAM specific objects
34 #include "libcli/ldap/ldap_ndr.h"
35 #include "ldb_module.h"
36 #include "auth/auth.h"
37 #include "dsdb/samdb/samdb.h"
38 #include "dsdb/samdb/ldb_modules/util.h"
39 #include "dsdb/samdb/ldb_modules/ridalloc.h"
40 #include "libcli/security/security.h"
41 #include "librpc/gen_ndr/ndr_security.h"
43 #include "param/param.h"
44 #include "libds/common/flag_mapping.h"
45 #include "system/network.h"
48 enum samldb_add_type {
55 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
58 struct samldb_step *next;
63 struct ldb_module *module;
64 struct ldb_request *req;
66 /* used for add operations */
67 enum samldb_add_type type;
69 /* the resulting message */
70 struct ldb_message *msg;
72 /* used in "samldb_find_for_defaultObjectCategory" */
73 struct ldb_dn *dn, *res_dn;
75 /* all the async steps necessary to complete the operation */
76 struct samldb_step *steps;
77 struct samldb_step *curstep;
79 /* If someone set an ares to forward controls and response back to the caller */
80 struct ldb_reply *ares;
83 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
84 struct ldb_request *req)
86 struct ldb_context *ldb;
87 struct samldb_ctx *ac;
89 ldb = ldb_module_get_ctx(module);
91 ac = talloc_zero(req, struct samldb_ctx);
103 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
105 struct samldb_step *step, *stepper;
107 step = talloc_zero(ac, struct samldb_step);
109 return ldb_oom(ldb_module_get_ctx(ac->module));
114 if (ac->steps == NULL) {
118 if (ac->curstep == NULL)
119 return ldb_operr(ldb_module_get_ctx(ac->module));
120 for (stepper = ac->curstep; stepper->next != NULL;
121 stepper = stepper->next);
122 stepper->next = step;
128 static int samldb_first_step(struct samldb_ctx *ac)
130 if (ac->steps == NULL) {
131 return ldb_operr(ldb_module_get_ctx(ac->module));
134 ac->curstep = ac->steps;
135 return ac->curstep->fn(ac);
138 static int samldb_next_step(struct samldb_ctx *ac)
140 if (ac->curstep->next) {
141 ac->curstep = ac->curstep->next;
142 return ac->curstep->fn(ac);
145 /* We exit the samldb module here. If someone set an "ares" to forward
146 * controls and response back to the caller, use them. */
148 return ldb_module_done(ac->req, ac->ares->controls,
149 ac->ares->response, LDB_SUCCESS);
151 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
155 static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr,
156 const char *attr_conflict,
157 struct ldb_dn *base_dn)
159 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
160 const char * const no_attrs[] = { NULL };
161 struct ldb_result *res;
163 struct ldb_message_element *el;
166 el = dsdb_get_single_valued_attr(ac->msg, attr,
169 /* we are not affected */
173 if (el->num_values > 1) {
174 ldb_asprintf_errstring(ldb,
175 "samldb: %s has %u values, should be single-valued!",
176 attr, el->num_values);
177 return LDB_ERR_CONSTRAINT_VIOLATION;
178 } else if (el->num_values == 0) {
179 ldb_asprintf_errstring(ldb,
180 "samldb: new value for %s not provided for mandatory, single-valued attribute!",
182 return LDB_ERR_OBJECT_CLASS_VIOLATION;
184 if (el->values[0].length == 0) {
185 ldb_asprintf_errstring(ldb,
186 "samldb: %s is of zero length, should have a value!",
188 return LDB_ERR_OBJECT_CLASS_VIOLATION;
190 enc_str = ldb_binary_encode(ac, el->values[0]);
192 if (enc_str == NULL) {
193 return ldb_module_oom(ac->module);
196 /* Make sure that attr (eg) "sAMAccountName" is only used once */
198 if (attr_conflict != NULL) {
199 ret = dsdb_module_search(ac->module, ac, &res,
201 LDB_SCOPE_SUBTREE, no_attrs,
202 DSDB_FLAG_NEXT_MODULE, ac->req,
205 attr_conflict, enc_str);
207 ret = dsdb_module_search(ac->module, ac, &res,
209 LDB_SCOPE_SUBTREE, no_attrs,
210 DSDB_FLAG_NEXT_MODULE, ac->req,
211 "(%s=%s)", attr, enc_str);
213 if (ret != LDB_SUCCESS) {
216 if (res->count > 1) {
217 return ldb_operr(ldb);
218 } else if (res->count == 1) {
219 if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0) {
220 ldb_asprintf_errstring(ldb,
221 "samldb: %s '%s' already in use!",
223 return LDB_ERR_ENTRY_ALREADY_EXISTS;
231 static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac)
233 int ret = samldb_unique_attr_check(ac, "samAccountName", NULL,
234 ldb_get_default_basedn(
235 ldb_module_get_ctx(ac->module)));
236 if (ret == LDB_ERR_OBJECT_CLASS_VIOLATION) {
237 ret = LDB_ERR_CONSTRAINT_VIOLATION;
242 static int samldb_schema_attributeid_valid_check(struct samldb_ctx *ac)
244 int ret = samldb_unique_attr_check(ac, "attributeID", "governsID",
245 ldb_get_schema_basedn(
246 ldb_module_get_ctx(ac->module)));
247 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
248 ret = LDB_ERR_UNWILLING_TO_PERFORM;
253 static int samldb_schema_governsid_valid_check(struct samldb_ctx *ac)
255 int ret = samldb_unique_attr_check(ac, "governsID", "attributeID",
256 ldb_get_schema_basedn(
257 ldb_module_get_ctx(ac->module)));
258 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
259 ret = LDB_ERR_UNWILLING_TO_PERFORM;
264 static int samldb_schema_ldapdisplayname_valid_check(struct samldb_ctx *ac)
266 int ret = samldb_unique_attr_check(ac, "lDAPDisplayName", NULL,
267 ldb_get_schema_basedn(
268 ldb_module_get_ctx(ac->module)));
269 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
270 ret = LDB_ERR_UNWILLING_TO_PERFORM;
276 /* sAMAccountName handling */
278 static int samldb_generate_sAMAccountName(struct ldb_context *ldb,
279 struct ldb_message *msg)
283 /* Format: $000000-000000000000 */
285 name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
286 (unsigned int)generate_random(),
287 (unsigned int)generate_random(),
288 (unsigned int)generate_random());
292 return ldb_msg_add_steal_string(msg, "sAMAccountName", name);
295 static int samldb_check_sAMAccountName(struct samldb_ctx *ac)
297 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
300 if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) {
301 ret = samldb_generate_sAMAccountName(ldb, ac->msg);
302 if (ret != LDB_SUCCESS) {
307 ret = samldb_sam_accountname_valid_check(ac);
308 if (ret != LDB_SUCCESS) {
312 return samldb_next_step(ac);
316 static bool samldb_msg_add_sid(struct ldb_message *msg,
318 const struct dom_sid *sid)
321 enum ndr_err_code ndr_err;
323 ndr_err = ndr_push_struct_blob(&v, msg, sid,
324 (ndr_push_flags_fn_t)ndr_push_dom_sid);
325 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
328 return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
332 /* allocate a SID using our RID Set */
333 static int samldb_allocate_sid(struct samldb_ctx *ac)
337 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
340 ret = ridalloc_allocate_rid(ac->module, &rid, ac->req);
341 if (ret != LDB_SUCCESS) {
345 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
347 return ldb_module_oom(ac->module);
350 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
351 return ldb_operr(ldb);
354 return samldb_next_step(ac);
358 see if a krbtgt_number is available
360 static bool samldb_krbtgtnumber_available(struct samldb_ctx *ac,
361 uint32_t krbtgt_number)
363 TALLOC_CTX *tmp_ctx = talloc_new(ac);
364 struct ldb_result *res;
365 const char * const no_attrs[] = { NULL };
368 ret = dsdb_module_search(ac->module, tmp_ctx, &res,
369 ldb_get_default_basedn(ldb_module_get_ctx(ac->module)),
370 LDB_SCOPE_SUBTREE, no_attrs,
371 DSDB_FLAG_NEXT_MODULE,
373 "(msDC-SecondaryKrbTgtNumber=%u)",
375 if (ret == LDB_SUCCESS && res->count == 0) {
376 talloc_free(tmp_ctx);
379 talloc_free(tmp_ctx);
383 /* special handling for add in RODC join */
384 static int samldb_rodc_add(struct samldb_ctx *ac)
386 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
387 uint32_t krbtgt_number, i_start, i;
390 struct ldb_val newpass_utf16;
392 /* find a unused msDC-SecondaryKrbTgtNumber */
393 i_start = generate_random() & 0xFFFF;
398 for (i=i_start; i<=0xFFFF; i++) {
399 if (samldb_krbtgtnumber_available(ac, i)) {
404 for (i=1; i<i_start; i++) {
405 if (samldb_krbtgtnumber_available(ac, i)) {
411 ldb_asprintf_errstring(ldb,
412 "%08X: Unable to find available msDS-SecondaryKrbTgtNumber",
413 W_ERROR_V(WERR_NO_SYSTEM_RESOURCES));
414 return LDB_ERR_OTHER;
417 ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber",
418 LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL);
419 if (ret != LDB_SUCCESS) {
420 return ldb_operr(ldb);
423 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
424 "msDS-SecondaryKrbTgtNumber", krbtgt_number);
425 if (ret != LDB_SUCCESS) {
426 return ldb_operr(ldb);
429 ret = ldb_msg_add_fmt(ac->msg, "sAMAccountName", "krbtgt_%u",
431 if (ret != LDB_SUCCESS) {
432 return ldb_operr(ldb);
435 newpass = generate_random_password(ac->msg, 128, 255);
436 if (newpass == NULL) {
437 return ldb_operr(ldb);
440 if (!convert_string_talloc(ac,
442 newpass, strlen(newpass),
443 (void *)&newpass_utf16.data,
444 &newpass_utf16.length)) {
445 ldb_asprintf_errstring(ldb,
447 "failed to generate UTF16 password from random password");
448 return LDB_ERR_OPERATIONS_ERROR;
450 ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
451 if (ret != LDB_SUCCESS) {
452 return ldb_operr(ldb);
455 return samldb_next_step(ac);
458 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
460 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
461 struct ldb_result *res;
462 const char * const no_attrs[] = { NULL };
467 ret = dsdb_module_search(ac->module, ac, &res,
468 ac->dn, LDB_SCOPE_BASE, no_attrs,
469 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
470 | DSDB_FLAG_NEXT_MODULE,
472 "(objectClass=classSchema)");
473 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
474 /* Don't be pricky when the DN doesn't exist if we have the */
475 /* RELAX control specified */
476 if (ldb_request_get_control(ac->req,
477 LDB_CONTROL_RELAX_OID) == NULL) {
478 ldb_set_errstring(ldb,
479 "samldb_find_defaultObjectCategory: "
480 "Invalid DN for 'defaultObjectCategory'!");
481 return LDB_ERR_CONSTRAINT_VIOLATION;
484 if ((ret != LDB_ERR_NO_SUCH_OBJECT) && (ret != LDB_SUCCESS)) {
488 if (ret == LDB_SUCCESS) {
489 /* ensure the defaultObjectCategory has a full GUID */
490 struct ldb_message *m;
491 m = ldb_msg_new(ac->msg);
496 if (ldb_msg_add_string(m, "defaultObjectCategory",
497 ldb_dn_get_extended_linearized(m, res->msgs[0]->dn, 1)) !=
501 m->elements[0].flags = LDB_FLAG_MOD_REPLACE;
503 ret = dsdb_module_modify(ac->module, m,
504 DSDB_FLAG_NEXT_MODULE,
506 if (ret != LDB_SUCCESS) {
514 return samldb_next_step(ac);
518 * msDS-IntId attributeSchema attribute handling
519 * during LDB_ADD request processing
521 static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
526 int32_t system_flags;
527 struct ldb_context *ldb;
528 struct ldb_result *ldb_res;
529 struct ldb_dn *schema_dn;
530 struct samldb_msds_intid_persistant *msds_intid_struct;
531 struct dsdb_schema *schema;
533 ldb = ldb_module_get_ctx(ac->module);
534 schema_dn = ldb_get_schema_basedn(ldb);
536 /* replicated update should always go through */
537 if (ldb_request_get_control(ac->req,
538 DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
542 /* msDS-IntId is handled by system and should never be
543 * passed by clients */
544 if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
545 return LDB_ERR_UNWILLING_TO_PERFORM;
548 /* do not generate msDS-IntId if Relax control is passed */
549 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
553 /* check Functional Level */
554 if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
558 /* check systemFlags for SCHEMA_BASE_OBJECT flag */
559 system_flags = ldb_msg_find_attr_as_int(ac->msg, "systemFlags", 0);
560 if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
563 schema = dsdb_get_schema(ldb, NULL);
565 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
566 "samldb_schema_info_update: no dsdb_schema loaded");
567 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
568 return ldb_operr(ldb);
571 msds_intid_struct = (struct samldb_msds_intid_persistant*) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE);
572 if (!msds_intid_struct) {
573 msds_intid_struct = talloc(ldb, struct samldb_msds_intid_persistant);
574 /* Generate new value for msDs-IntId
575 * Value should be in 0x80000000..0xBFFFFFFF range */
576 msds_intid = generate_random() % 0X3FFFFFFF;
577 msds_intid += 0x80000000;
578 msds_intid_struct->msds_intid = msds_intid;
579 msds_intid_struct->usn = schema->loaded_usn;
580 DEBUG(2, ("No samldb_msds_intid_persistant struct, allocating a new one\n"));
582 msds_intid = msds_intid_struct->msds_intid;
585 /* probe id values until unique one is found */
587 uint64_t current_usn;
589 if (msds_intid > 0xBFFFFFFF) {
590 msds_intid = 0x80000001;
593 * Alternative strategy to a costly (even indexed search) to the
595 * We search in the schema if we have already this intid (using dsdb_attribute_by_attributeID_id because
596 * in the range 0x80000000 0xBFFFFFFFF, attributeID is a DSDB_ATTID_TYPE_INTID).
597 * If so generate another random value.
598 * If not check if the highest USN in the database for the schema partition is the
600 * If so it means that's only this ldb context that is touching the schema in the database.
601 * If not it means that's someone else has modified the database while we are doing our changes too
602 * (this case should be very bery rare) in order to be sure do the search in the database.
604 if (dsdb_attribute_by_attributeID_id(schema, msds_intid)) {
605 msds_intid = generate_random() % 0X3FFFFFFF;
606 msds_intid += 0x80000000;
610 ret = dsdb_module_load_partition_usn(ac->module, schema_dn,
611 ¤t_usn, NULL, NULL);
612 if (ret != LDB_SUCCESS) {
613 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
614 __location__": Searching for schema USN failed: %s\n",
616 return ldb_operr(ldb);
619 /* current_usn can be lesser than msds_intid_struct-> if there is
620 * uncommited changes.
622 if (current_usn > msds_intid_struct->usn) {
623 /* oups something has changed, someone/something
624 * else is modifying or has modified the schema
625 * we'd better check this intid is the database directly
628 DEBUG(2, ("Schema has changed, searching the database for the unicity of %d\n",
631 ret = dsdb_module_search(ac->module, ac,
633 schema_dn, LDB_SCOPE_ONELEVEL, NULL,
634 DSDB_FLAG_NEXT_MODULE,
636 "(msDS-IntId=%d)", msds_intid);
637 if (ret != LDB_SUCCESS) {
638 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
639 __location__": Searching for msDS-IntId=%d failed - %s\n",
642 return ldb_operr(ldb);
644 id_exists = (ldb_res->count > 0);
645 talloc_free(ldb_res);
651 msds_intid_struct->msds_intid = msds_intid;
652 ldb_set_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE, msds_intid_struct);
654 return samdb_msg_add_int(ldb, ac->msg, ac->msg, "msDS-IntId",
660 * samldb_add_entry (async)
663 static int samldb_add_entry_callback(struct ldb_request *req,
664 struct ldb_reply *ares)
666 struct ldb_context *ldb;
667 struct samldb_ctx *ac;
670 ac = talloc_get_type(req->context, struct samldb_ctx);
671 ldb = ldb_module_get_ctx(ac->module);
674 return ldb_module_done(ac->req, NULL, NULL,
675 LDB_ERR_OPERATIONS_ERROR);
678 if (ares->type == LDB_REPLY_REFERRAL) {
679 return ldb_module_send_referral(ac->req, ares->referral);
682 if (ares->error != LDB_SUCCESS) {
683 return ldb_module_done(ac->req, ares->controls,
684 ares->response, ares->error);
686 if (ares->type != LDB_REPLY_DONE) {
687 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
688 return ldb_module_done(ac->req, NULL, NULL,
689 LDB_ERR_OPERATIONS_ERROR);
692 /* The caller may wish to get controls back from the add */
693 ac->ares = talloc_steal(ac, ares);
695 ret = samldb_next_step(ac);
696 if (ret != LDB_SUCCESS) {
697 return ldb_module_done(ac->req, NULL, NULL, ret);
702 static int samldb_add_entry(struct samldb_ctx *ac)
704 struct ldb_context *ldb;
705 struct ldb_request *req;
708 ldb = ldb_module_get_ctx(ac->module);
710 ret = ldb_build_add_req(&req, ldb, ac,
713 ac, samldb_add_entry_callback,
715 LDB_REQ_SET_LOCATION(req);
716 if (ret != LDB_SUCCESS) {
720 return ldb_next_request(ac->module, req);
724 * return true if msg carries an attributeSchema that is intended to be RODC
725 * filtered but is also a system-critical attribute.
727 static bool check_rodc_critical_attribute(struct ldb_message *msg)
729 uint32_t schemaFlagsEx, searchFlags, rodc_filtered_flags;
731 schemaFlagsEx = ldb_msg_find_attr_as_uint(msg, "schemaFlagsEx", 0);
732 searchFlags = ldb_msg_find_attr_as_uint(msg, "searchFlags", 0);
733 rodc_filtered_flags = (SEARCH_FLAG_RODC_ATTRIBUTE
734 | SEARCH_FLAG_CONFIDENTIAL);
736 if ((schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) &&
737 ((searchFlags & rodc_filtered_flags) == rodc_filtered_flags)) {
745 static int samldb_fill_object(struct samldb_ctx *ac)
747 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
750 /* Add information for the different account types */
752 case SAMLDB_TYPE_USER: {
753 struct ldb_control *rodc_control = ldb_request_get_control(ac->req,
754 LDB_CONTROL_RODC_DCPROMO_OID);
755 if (rodc_control != NULL) {
756 /* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
757 rodc_control->critical = false;
758 ret = samldb_add_step(ac, samldb_rodc_add);
759 if (ret != LDB_SUCCESS) return ret;
762 /* check if we have a valid sAMAccountName */
763 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
764 if (ret != LDB_SUCCESS) return ret;
766 ret = samldb_add_step(ac, samldb_add_entry);
767 if (ret != LDB_SUCCESS) return ret;
771 case SAMLDB_TYPE_GROUP: {
772 /* check if we have a valid sAMAccountName */
773 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
774 if (ret != LDB_SUCCESS) return ret;
776 ret = samldb_add_step(ac, samldb_add_entry);
777 if (ret != LDB_SUCCESS) return ret;
781 case SAMLDB_TYPE_CLASS: {
782 const char *lDAPDisplayName = NULL;
783 const struct ldb_val *rdn_value, *def_obj_cat_val;
784 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "objectClassCategory", -2);
786 /* As discussed with Microsoft through dochelp in April 2012 this is the behavior of windows*/
787 if (!ldb_msg_find_element(ac->msg, "subClassOf")) {
788 ret = ldb_msg_add_string(ac->msg, "subClassOf", "top");
789 if (ret != LDB_SUCCESS) return ret;
792 ret = samdb_find_or_add_attribute(ldb, ac->msg,
794 if (ret != LDB_SUCCESS) return ret;
796 /* do not allow one to mark an attributeSchema as RODC filtered if it
797 * is system-critical */
798 if (check_rodc_critical_attribute(ac->msg)) {
799 ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
800 ldb_dn_get_linearized(ac->msg->dn));
801 return LDB_ERR_UNWILLING_TO_PERFORM;
804 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
805 if (rdn_value == NULL) {
806 return ldb_operr(ldb);
808 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
809 /* the RDN has prefix "CN" */
810 ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
811 samdb_cn_to_lDAPDisplayName(ac->msg,
812 (const char *) rdn_value->data));
813 if (ret != LDB_SUCCESS) {
819 lDAPDisplayName = ldb_msg_find_attr_as_string(ac->msg,
822 ret = ldb_valid_attr_name(lDAPDisplayName);
824 lDAPDisplayName[0] == '*' ||
825 lDAPDisplayName[0] == '@')
827 return dsdb_module_werror(ac->module,
828 LDB_ERR_UNWILLING_TO_PERFORM,
829 WERR_DS_INVALID_LDAP_DISPLAY_NAME,
830 "lDAPDisplayName is invalid");
833 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
836 guid = GUID_random();
837 ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
838 if (ret != LDB_SUCCESS) {
844 def_obj_cat_val = ldb_msg_find_ldb_val(ac->msg,
845 "defaultObjectCategory");
846 if (def_obj_cat_val != NULL) {
847 /* "defaultObjectCategory" has been set by the caller.
848 * Do some checks for consistency.
849 * NOTE: The real constraint check (that
850 * 'defaultObjectCategory' is the DN of the new
851 * objectclass or any parent of it) is still incomplete.
852 * For now we say that 'defaultObjectCategory' is valid
853 * if it exists and it is of objectclass "classSchema".
855 ac->dn = ldb_dn_from_ldb_val(ac, ldb, def_obj_cat_val);
856 if (ac->dn == NULL) {
857 ldb_set_errstring(ldb,
858 "Invalid DN for 'defaultObjectCategory'!");
859 return LDB_ERR_CONSTRAINT_VIOLATION;
862 /* "defaultObjectCategory" has not been set by the
863 * caller. Use the entry DN for it. */
864 ac->dn = ac->msg->dn;
866 ret = ldb_msg_add_string(ac->msg, "defaultObjectCategory",
867 ldb_dn_alloc_linearized(ac->msg, ac->dn));
868 if (ret != LDB_SUCCESS) {
874 ret = samldb_add_step(ac, samldb_add_entry);
875 if (ret != LDB_SUCCESS) return ret;
877 /* Now perform the checks for the 'defaultObjectCategory'. The
878 * lookup DN was already saved in "ac->dn" */
879 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
880 if (ret != LDB_SUCCESS) return ret;
882 /* -2 is not a valid objectClassCategory so it means the attribute wasn't present */
884 /* Windows 2003 does this*/
885 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "objectClassCategory", 0);
886 if (ret != LDB_SUCCESS) {
893 case SAMLDB_TYPE_ATTRIBUTE: {
894 const char *lDAPDisplayName = NULL;
895 const struct ldb_val *rdn_value;
896 struct ldb_message_element *el;
897 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
898 if (rdn_value == NULL) {
899 return ldb_operr(ldb);
901 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
902 /* the RDN has prefix "CN" */
903 ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
904 samdb_cn_to_lDAPDisplayName(ac->msg,
905 (const char *) rdn_value->data));
906 if (ret != LDB_SUCCESS) {
912 lDAPDisplayName = ldb_msg_find_attr_as_string(ac->msg,
915 ret = ldb_valid_attr_name(lDAPDisplayName);
917 lDAPDisplayName[0] == '*' ||
918 lDAPDisplayName[0] == '@')
920 return dsdb_module_werror(ac->module,
921 LDB_ERR_UNWILLING_TO_PERFORM,
922 WERR_DS_INVALID_LDAP_DISPLAY_NAME,
923 "lDAPDisplayName is invalid");
926 /* do not allow one to mark an attributeSchema as RODC filtered if it
927 * is system-critical */
928 if (check_rodc_critical_attribute(ac->msg)) {
929 ldb_asprintf_errstring(ldb,
930 "samldb: refusing schema add of %s - cannot combine critical attribute with RODC filtering",
931 ldb_dn_get_linearized(ac->msg->dn));
932 return LDB_ERR_UNWILLING_TO_PERFORM;
935 ret = samdb_find_or_add_attribute(ldb, ac->msg,
936 "isSingleValued", "FALSE");
937 if (ret != LDB_SUCCESS) return ret;
939 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
942 guid = GUID_random();
943 ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
944 if (ret != LDB_SUCCESS) {
950 el = ldb_msg_find_element(ac->msg, "attributeSyntax");
953 * No need to scream if there isn't as we have code later on
954 * that will take care of it.
956 const struct dsdb_syntax *syntax = find_syntax_map_by_ad_oid((const char *)el->values[0].data);
958 DEBUG(9, ("Can't find dsdb_syntax object for attributeSyntax %s\n",
959 (const char *)el->values[0].data));
961 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "oMSyntax", 0);
962 const struct ldb_val *val = ldb_msg_find_ldb_val(ac->msg, "oMObjectClass");
965 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "oMSyntax", syntax->oMSyntax);
966 if (ret != LDB_SUCCESS) {
971 struct ldb_val val2 = ldb_val_dup(ldb, &syntax->oMObjectClass);
972 if (val2.length > 0) {
973 ret = ldb_msg_add_value(ac->msg, "oMObjectClass", &val2, NULL);
974 if (ret != LDB_SUCCESS) {
982 /* handle msDS-IntID attribute */
983 ret = samldb_add_handle_msDS_IntId(ac);
984 if (ret != LDB_SUCCESS) return ret;
986 ret = samldb_add_step(ac, samldb_add_entry);
987 if (ret != LDB_SUCCESS) return ret;
992 ldb_asprintf_errstring(ldb, "Invalid entry type!");
993 return LDB_ERR_OPERATIONS_ERROR;
997 return samldb_first_step(ac);
1000 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1002 struct ldb_context *ldb;
1003 const struct ldb_val *rdn_value;
1004 struct dom_sid *sid;
1007 ldb = ldb_module_get_ctx(ac->module);
1009 sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1011 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1012 if (rdn_value == NULL) {
1013 return ldb_operr(ldb);
1015 sid = dom_sid_parse_talloc(ac->msg,
1016 (const char *)rdn_value->data);
1018 ldb_set_errstring(ldb,
1019 "samldb: No valid SID found in ForeignSecurityPrincipal CN!");
1020 return LDB_ERR_CONSTRAINT_VIOLATION;
1022 if (! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
1023 return ldb_operr(ldb);
1027 /* finally proceed with adding the entry */
1028 ret = samldb_add_step(ac, samldb_add_entry);
1029 if (ret != LDB_SUCCESS) return ret;
1031 return samldb_first_step(ac);
1034 static int samldb_schema_info_update(struct samldb_ctx *ac)
1037 struct ldb_context *ldb;
1038 struct dsdb_schema *schema;
1040 /* replicated update should always go through */
1041 if (ldb_request_get_control(ac->req,
1042 DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1046 /* do not update schemaInfo during provisioning */
1047 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1051 ldb = ldb_module_get_ctx(ac->module);
1052 schema = dsdb_get_schema(ldb, NULL);
1054 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1055 "samldb_schema_info_update: no dsdb_schema loaded");
1056 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1057 return ldb_operr(ldb);
1060 ret = dsdb_module_schema_info_update(ac->module, schema,
1061 DSDB_FLAG_NEXT_MODULE|
1062 DSDB_FLAG_AS_SYSTEM,
1064 if (ret != LDB_SUCCESS) {
1065 ldb_asprintf_errstring(ldb,
1066 "samldb_schema_info_update: dsdb_module_schema_info_update failed with %s",
1067 ldb_errstring(ldb));
1074 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
1075 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
1076 struct dom_sid *sid,
1078 uint32_t user_account_control,
1079 uint32_t user_account_control_old);
1082 * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
1084 * Has to be invoked on "add" and "modify" operations on "user", "computer" and
1086 * ac->msg contains the "add"/"modify" message
1087 * ac->type contains the object type (main objectclass)
1089 static int samldb_objectclass_trigger(struct samldb_ctx *ac)
1091 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1092 void *skip_allocate_sids = ldb_get_opaque(ldb,
1093 "skip_allocate_sids");
1094 struct ldb_message_element *el, *el2;
1095 struct dom_sid *sid;
1098 /* make sure that "sAMAccountType" is not specified */
1099 el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1101 ldb_set_errstring(ldb,
1102 "samldb: sAMAccountType must not be specified!");
1103 return LDB_ERR_UNWILLING_TO_PERFORM;
1106 /* Step 1: objectSid assignment */
1108 /* Don't allow the objectSid to be changed. But beside the RELAX
1109 * control we have also to guarantee that it can always be set with
1110 * SYSTEM permissions. This is needed for the "samba3sam" backend. */
1111 sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1112 if ((sid != NULL) && (!dsdb_module_am_system(ac->module)) &&
1113 (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
1114 ldb_set_errstring(ldb,
1115 "samldb: objectSid must not be specified!");
1116 return LDB_ERR_UNWILLING_TO_PERFORM;
1119 /* but generate a new SID when we do have an add operations */
1120 if ((sid == NULL) && (ac->req->operation == LDB_ADD) && !skip_allocate_sids) {
1121 ret = samldb_add_step(ac, samldb_allocate_sid);
1122 if (ret != LDB_SUCCESS) return ret;
1126 case SAMLDB_TYPE_USER: {
1127 bool uac_generated = false, uac_add_flags = false;
1129 /* Step 1.2: Default values */
1130 ret = dsdb_user_obj_set_defaults(ldb, ac->msg, ac->req);
1131 if (ret != LDB_SUCCESS) return ret;
1133 /* On add operations we might need to generate a
1134 * "userAccountControl" (if it isn't specified). */
1135 el = ldb_msg_find_element(ac->msg, "userAccountControl");
1136 if ((el == NULL) && (ac->req->operation == LDB_ADD)) {
1137 ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1138 "userAccountControl",
1140 if (ret != LDB_SUCCESS) {
1143 uac_generated = true;
1144 uac_add_flags = true;
1147 el = ldb_msg_find_element(ac->msg, "userAccountControl");
1150 uint32_t user_account_control;
1151 /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */
1152 user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
1153 "userAccountControl",
1155 raw_uac = user_account_control;
1157 * "userAccountControl" = 0 or missing one of
1158 * the types means "UF_NORMAL_ACCOUNT". See
1159 * MS-SAMR 3.1.1.8.10 point 8
1161 if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) {
1162 user_account_control = UF_NORMAL_ACCOUNT | user_account_control;
1163 uac_generated = true;
1167 * As per MS-SAMR 3.1.1.8.10 these flags have not to be set
1169 if ((user_account_control & UF_LOCKOUT) != 0) {
1170 user_account_control &= ~UF_LOCKOUT;
1171 uac_generated = true;
1173 if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) {
1174 user_account_control &= ~UF_PASSWORD_EXPIRED;
1175 uac_generated = true;
1178 ret = samldb_check_user_account_control_rules(ac, NULL,
1180 user_account_control,
1182 if (ret != LDB_SUCCESS) {
1186 /* Workstation and (read-only) DC objects do need objectclass "computer" */
1187 if ((samdb_find_attribute(ldb, ac->msg,
1188 "objectclass", "computer") == NULL) &&
1189 (user_account_control &
1190 (UF_SERVER_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT))) {
1191 ldb_set_errstring(ldb,
1192 "samldb: Requested account type does need objectclass 'computer'!");
1193 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1196 /* add "sAMAccountType" attribute */
1197 ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL);
1198 if (ret != LDB_SUCCESS) {
1202 /* "isCriticalSystemObject" might be set */
1203 if (user_account_control &
1204 (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
1205 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1207 if (ret != LDB_SUCCESS) {
1210 el2 = ldb_msg_find_element(ac->msg,
1211 "isCriticalSystemObject");
1212 el2->flags = LDB_FLAG_MOD_REPLACE;
1213 } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
1214 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1216 if (ret != LDB_SUCCESS) {
1219 el2 = ldb_msg_find_element(ac->msg,
1220 "isCriticalSystemObject");
1221 el2->flags = LDB_FLAG_MOD_REPLACE;
1224 /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */
1225 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
1228 ret = dsdb_user_obj_set_primary_group_id(ldb, ac->msg, user_account_control, &rid);
1229 if (ret != LDB_SUCCESS) {
1233 * Older AD deployments don't know about the
1236 if (rid == DOMAIN_RID_READONLY_DCS) {
1237 ret = samldb_prim_group_tester(ac, rid);
1238 if (ret != LDB_SUCCESS) {
1244 /* Step 1.5: Add additional flags when needed */
1245 /* Obviously this is done when the "userAccountControl"
1246 * has been generated here (tested against Windows
1248 if (uac_generated) {
1249 if (uac_add_flags) {
1250 user_account_control |= UF_ACCOUNTDISABLE;
1251 user_account_control |= UF_PASSWD_NOTREQD;
1254 ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1255 "userAccountControl",
1256 user_account_control);
1257 if (ret != LDB_SUCCESS) {
1266 case SAMLDB_TYPE_GROUP: {
1267 const char *tempstr;
1269 /* Step 2.2: Default values */
1270 tempstr = talloc_asprintf(ac->msg, "%d",
1271 GTYPE_SECURITY_GLOBAL_GROUP);
1272 if (tempstr == NULL) return ldb_operr(ldb);
1273 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1274 "groupType", tempstr);
1275 if (ret != LDB_SUCCESS) return ret;
1277 /* Step 2.3: "groupType" -> "sAMAccountType" */
1278 el = ldb_msg_find_element(ac->msg, "groupType");
1280 uint32_t group_type, account_type;
1282 group_type = ldb_msg_find_attr_as_uint(ac->msg,
1285 /* The creation of builtin groups requires the
1287 if (group_type == GTYPE_SECURITY_BUILTIN_LOCAL_GROUP) {
1288 if (ldb_request_get_control(ac->req,
1289 LDB_CONTROL_RELAX_OID) == NULL) {
1290 return LDB_ERR_UNWILLING_TO_PERFORM;
1294 account_type = ds_gtype2atype(group_type);
1295 if (account_type == 0) {
1296 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1297 return LDB_ERR_UNWILLING_TO_PERFORM;
1299 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1302 if (ret != LDB_SUCCESS) {
1305 el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
1306 el2->flags = LDB_FLAG_MOD_REPLACE;
1312 ldb_asprintf_errstring(ldb,
1313 "Invalid entry type!");
1314 return LDB_ERR_OPERATIONS_ERROR;
1322 * "Primary group ID" trigger (MS-SAMR 3.1.1.8.2)
1324 * Has to be invoked on "add" and "modify" operations on "user" and "computer"
1326 * ac->msg contains the "add"/"modify" message
1329 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid)
1331 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1332 struct dom_sid *sid;
1333 struct ldb_result *res;
1335 const char * const noattrs[] = { NULL };
1337 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1339 return ldb_operr(ldb);
1342 ret = dsdb_module_search(ac->module, ac, &res,
1343 ldb_get_default_basedn(ldb),
1345 noattrs, DSDB_FLAG_NEXT_MODULE,
1348 ldap_encode_ndr_dom_sid(ac, sid));
1349 if (ret != LDB_SUCCESS) {
1352 if (res->count != 1) {
1354 ldb_asprintf_errstring(ldb,
1355 "Failed to find primary group with RID %u!",
1357 return LDB_ERR_UNWILLING_TO_PERFORM;
1364 static int samldb_prim_group_set(struct samldb_ctx *ac)
1366 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1369 rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
1370 if (rid == (uint32_t) -1) {
1371 /* we aren't affected of any primary group set */
1374 } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1375 ldb_set_errstring(ldb,
1376 "The primary group isn't settable on add operations!");
1377 return LDB_ERR_UNWILLING_TO_PERFORM;
1380 return samldb_prim_group_tester(ac, rid);
1383 static int samldb_prim_group_change(struct samldb_ctx *ac)
1385 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1386 const char * const attrs[] = {
1389 "userAccountControl",
1391 struct ldb_result *res, *group_res;
1392 struct ldb_message_element *el;
1393 struct ldb_message *msg;
1394 uint32_t prev_rid, new_rid, uac;
1395 struct dom_sid *prev_sid, *new_sid;
1396 struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1398 const char * const noattrs[] = { NULL };
1400 el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID",
1401 ac->req->operation);
1403 /* we are not affected */
1407 /* Fetch information from the existing object */
1409 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1410 DSDB_FLAG_NEXT_MODULE, ac->req);
1411 if (ret != LDB_SUCCESS) {
1415 uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1417 /* Finds out the DN of the old primary group */
1419 prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID",
1421 if (prev_rid == (uint32_t) -1) {
1422 /* User objects do always have a mandatory "primaryGroupID"
1423 * attribute. If this doesn't exist then the object is of the
1424 * wrong type. This is the exact Windows error code */
1425 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1428 prev_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), prev_rid);
1429 if (prev_sid == NULL) {
1430 return ldb_operr(ldb);
1433 /* Finds out the DN of the new primary group
1434 * Notice: in order to parse the primary group ID correctly we create
1435 * a temporary message here. */
1437 msg = ldb_msg_new(ac->msg);
1439 return ldb_module_oom(ac->module);
1441 ret = ldb_msg_add(msg, el, 0);
1442 if (ret != LDB_SUCCESS) {
1445 new_rid = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", (uint32_t) -1);
1447 if (new_rid == (uint32_t) -1) {
1448 /* we aren't affected of any primary group change */
1452 if (prev_rid == new_rid) {
1456 if ((uac & UF_SERVER_TRUST_ACCOUNT) && new_rid != DOMAIN_RID_DCS) {
1457 ldb_asprintf_errstring(ldb,
1458 "%08X: samldb: UF_SERVER_TRUST_ACCOUNT requires "
1459 "primaryGroupID=%u!",
1460 W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
1462 return LDB_ERR_UNWILLING_TO_PERFORM;
1465 if ((uac & UF_PARTIAL_SECRETS_ACCOUNT) && new_rid != DOMAIN_RID_READONLY_DCS) {
1466 ldb_asprintf_errstring(ldb,
1467 "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT requires "
1468 "primaryGroupID=%u!",
1469 W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
1470 DOMAIN_RID_READONLY_DCS);
1471 return LDB_ERR_UNWILLING_TO_PERFORM;
1474 ret = dsdb_module_search(ac->module, ac, &group_res,
1475 ldb_get_default_basedn(ldb),
1477 noattrs, DSDB_FLAG_NEXT_MODULE,
1480 ldap_encode_ndr_dom_sid(ac, prev_sid));
1481 if (ret != LDB_SUCCESS) {
1484 if (group_res->count != 1) {
1485 return ldb_operr(ldb);
1487 prev_prim_group_dn = group_res->msgs[0]->dn;
1489 new_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), new_rid);
1490 if (new_sid == NULL) {
1491 return ldb_operr(ldb);
1494 ret = dsdb_module_search(ac->module, ac, &group_res,
1495 ldb_get_default_basedn(ldb),
1497 noattrs, DSDB_FLAG_NEXT_MODULE,
1500 ldap_encode_ndr_dom_sid(ac, new_sid));
1501 if (ret != LDB_SUCCESS) {
1504 if (group_res->count != 1) {
1505 /* Here we know if the specified new primary group candidate is
1507 return LDB_ERR_UNWILLING_TO_PERFORM;
1509 new_prim_group_dn = group_res->msgs[0]->dn;
1511 /* We need to be already a normal member of the new primary
1512 * group in order to be successful. */
1513 el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1514 ldb_dn_get_linearized(new_prim_group_dn));
1516 return LDB_ERR_UNWILLING_TO_PERFORM;
1519 /* Remove the "member" attribute on the new primary group */
1520 msg = ldb_msg_new(ac->msg);
1522 return ldb_module_oom(ac->module);
1524 msg->dn = new_prim_group_dn;
1526 ret = samdb_msg_add_delval(ldb, msg, msg, "member",
1527 ldb_dn_get_linearized(ac->msg->dn));
1528 if (ret != LDB_SUCCESS) {
1532 ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1533 if (ret != LDB_SUCCESS) {
1538 /* Add a "member" attribute for the previous primary group */
1539 msg = ldb_msg_new(ac->msg);
1541 return ldb_module_oom(ac->module);
1543 msg->dn = prev_prim_group_dn;
1545 ret = samdb_msg_add_addval(ldb, msg, msg, "member",
1546 ldb_dn_get_linearized(ac->msg->dn));
1547 if (ret != LDB_SUCCESS) {
1551 ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1552 if (ret != LDB_SUCCESS) {
1560 static int samldb_prim_group_trigger(struct samldb_ctx *ac)
1564 if (ac->req->operation == LDB_ADD) {
1565 ret = samldb_prim_group_set(ac);
1567 ret = samldb_prim_group_change(ac);
1573 static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac,
1574 uint32_t user_account_control)
1577 bool need_check = false;
1578 const struct uac_to_guid {
1583 const char *error_string;
1586 .uac = UF_TEMP_DUPLICATE_ACCOUNT,
1588 .error_string = "Updating the UF_TEMP_DUPLICATE_ACCOUNT flag is never allowed"
1591 .uac = UF_PARTIAL_SECRETS_ACCOUNT,
1592 .needs = UF_WORKSTATION_TRUST_ACCOUNT,
1593 .error_string = "Setting UF_PARTIAL_SECRETS_ACCOUNT only permitted with UF_WORKSTATION_TRUST_ACCOUNT"
1596 .uac = UF_TRUSTED_FOR_DELEGATION,
1597 .not_with = UF_PARTIAL_SECRETS_ACCOUNT,
1598 .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
1601 .uac = UF_NORMAL_ACCOUNT,
1602 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_NORMAL_ACCOUNT,
1603 .error_string = "Setting more than one account type not permitted"
1606 .uac = UF_WORKSTATION_TRUST_ACCOUNT,
1607 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_WORKSTATION_TRUST_ACCOUNT,
1608 .error_string = "Setting more than one account type not permitted"
1611 .uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
1612 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_INTERDOMAIN_TRUST_ACCOUNT,
1613 .error_string = "Setting more than one account type not permitted"
1616 .uac = UF_SERVER_TRUST_ACCOUNT,
1617 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_SERVER_TRUST_ACCOUNT,
1618 .error_string = "Setting more than one account type not permitted"
1621 .uac = UF_TRUSTED_FOR_DELEGATION,
1622 .not_with = UF_PARTIAL_SECRETS_ACCOUNT,
1623 .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
1627 for (i = 0; i < ARRAY_SIZE(map); i++) {
1628 if (user_account_control & map[i].uac) {
1633 if (need_check == false) {
1637 for (i = 0; i < ARRAY_SIZE(map); i++) {
1638 uint32_t this_uac = user_account_control & map[i].uac;
1639 if (this_uac != 0) {
1641 ret = LDB_ERR_OTHER;
1643 } else if (map[i].needs != 0) {
1644 if ((map[i].needs & user_account_control) == 0) {
1645 ret = LDB_ERR_OTHER;
1648 } else if (map[i].not_with != 0) {
1649 if ((map[i].not_with & user_account_control) != 0) {
1650 ret = LDB_ERR_OTHER;
1656 if (ret != LDB_SUCCESS) {
1657 switch (ac->req->operation) {
1659 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
1660 "Failed to add %s: %s",
1661 ldb_dn_get_linearized(ac->msg->dn),
1662 map[i].error_string);
1665 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
1666 "Failed to modify %s: %s",
1667 ldb_dn_get_linearized(ac->msg->dn),
1668 map[i].error_string);
1671 return ldb_module_operr(ac->module);
1678 * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured
1681 static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
1682 struct dom_sid *sid,
1683 uint32_t user_account_control,
1684 uint32_t user_account_control_old)
1687 bool need_acl_check = false;
1688 struct ldb_result *res;
1689 const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL};
1690 struct security_token *user_token;
1691 struct security_descriptor *domain_sd;
1692 struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
1693 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1694 const struct uac_to_guid {
1696 uint32_t priv_to_change_from;
1699 enum sec_privilege privilege;
1700 bool delete_is_privileged;
1701 bool admin_required;
1702 const char *error_string;
1705 .uac = UF_PASSWD_NOTREQD,
1706 .guid = GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT,
1707 .error_string = "Adding the UF_PASSWD_NOTREQD bit in userAccountControl requires the Update-Password-Not-Required-Bit right that was not given on the Domain object"
1710 .uac = UF_DONT_EXPIRE_PASSWD,
1711 .guid = GUID_DRS_UNEXPIRE_PASSWORD,
1712 .error_string = "Adding the UF_DONT_EXPIRE_PASSWD bit in userAccountControl requires the Unexpire-Password right that was not given on the Domain object"
1715 .uac = UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED,
1716 .guid = GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD,
1717 .error_string = "Adding the UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED bit in userAccountControl requires the Enable-Per-User-Reversibly-Encrypted-Password right that was not given on the Domain object"
1720 .uac = UF_SERVER_TRUST_ACCOUNT,
1721 .guid = GUID_DRS_DS_INSTALL_REPLICA,
1722 .error_string = "Adding the UF_SERVER_TRUST_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object"
1725 .uac = UF_PARTIAL_SECRETS_ACCOUNT,
1726 .guid = GUID_DRS_DS_INSTALL_REPLICA,
1727 .error_string = "Adding the UF_PARTIAL_SECRETS_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object"
1730 .uac = UF_WORKSTATION_TRUST_ACCOUNT,
1731 .priv_to_change_from = UF_NORMAL_ACCOUNT,
1732 .error_string = "Swapping UF_NORMAL_ACCOUNT to UF_WORKSTATION_TRUST_ACCOUNT requires the user to be a member of the domain admins group"
1735 .uac = UF_NORMAL_ACCOUNT,
1736 .priv_to_change_from = UF_WORKSTATION_TRUST_ACCOUNT,
1737 .error_string = "Swapping UF_WORKSTATION_TRUST_ACCOUNT to UF_NORMAL_ACCOUNT requires the user to be a member of the domain admins group"
1740 .uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
1741 .oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1742 .error_string = "Updating the UF_INTERDOMAIN_TRUST_ACCOUNT bit in userAccountControl is not permitted over LDAP. This bit is restricted to the LSA CreateTrustedDomain interface",
1743 .delete_is_privileged = true
1746 .uac = UF_TRUSTED_FOR_DELEGATION,
1747 .privilege = SEC_PRIV_ENABLE_DELEGATION,
1748 .delete_is_privileged = true,
1749 .error_string = "Updating the UF_TRUSTED_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege"
1752 .uac = UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION,
1753 .privilege = SEC_PRIV_ENABLE_DELEGATION,
1754 .delete_is_privileged = true,
1755 .error_string = "Updating the UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege"
1760 if (dsdb_module_am_system(ac->module)) {
1764 for (i = 0; i < ARRAY_SIZE(map); i++) {
1765 if (user_account_control & map[i].uac) {
1766 need_acl_check = true;
1770 if (need_acl_check == false) {
1774 user_token = acl_user_token(ac->module);
1775 if (user_token == NULL) {
1776 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1779 ret = dsdb_module_search_dn(ac->module, ac, &res,
1782 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
1784 if (ret != LDB_SUCCESS) {
1787 if (res->count != 1) {
1788 return ldb_module_operr(ac->module);
1791 ret = dsdb_get_sd_from_ldb_message(ldb,
1792 ac, res->msgs[0], &domain_sd);
1794 if (ret != LDB_SUCCESS) {
1798 for (i = 0; i < ARRAY_SIZE(map); i++) {
1799 uint32_t this_uac_new = user_account_control & map[i].uac;
1800 uint32_t this_uac_old = user_account_control_old & map[i].uac;
1801 if (this_uac_new != this_uac_old) {
1802 if (this_uac_old != 0) {
1803 if (map[i].delete_is_privileged == false) {
1808 struct ldb_control *control = ldb_request_get_control(ac->req, map[i].oid);
1809 if (control == NULL) {
1810 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1812 } else if (map[i].privilege != SEC_PRIV_INVALID) {
1813 bool have_priv = security_token_has_privilege(user_token,
1815 if (have_priv == false) {
1816 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1818 } else if (map[i].priv_to_change_from & user_account_control_old) {
1819 bool is_admin = security_token_has_builtin_administrators(user_token);
1820 if (is_admin == false) {
1821 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1823 } else if (map[i].guid) {
1824 ret = acl_check_extended_right(ac, domain_sd,
1827 SEC_ADS_CONTROL_ACCESS,
1832 if (ret != LDB_SUCCESS) {
1837 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1838 switch (ac->req->operation) {
1840 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
1841 "Failed to add %s: %s",
1842 ldb_dn_get_linearized(ac->msg->dn),
1843 map[i].error_string);
1846 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
1847 "Failed to modify %s: %s",
1848 ldb_dn_get_linearized(ac->msg->dn),
1849 map[i].error_string);
1852 return ldb_module_operr(ac->module);
1855 dsdb_acl_debug(domain_sd, acl_user_token(ac->module),
1864 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
1865 struct dom_sid *sid,
1867 uint32_t user_account_control,
1868 uint32_t user_account_control_old)
1871 struct dsdb_control_password_user_account_control *uac = NULL;
1873 ret = samldb_check_user_account_control_invariants(ac, user_account_control);
1874 if (ret != LDB_SUCCESS) {
1877 ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old);
1878 if (ret != LDB_SUCCESS) {
1882 uac = talloc_zero(ac->req,
1883 struct dsdb_control_password_user_account_control);
1885 return ldb_module_oom(ac->module);
1888 uac->req_flags = req_uac;
1889 uac->old_flags = user_account_control_old;
1890 uac->new_flags = user_account_control;
1892 ret = ldb_request_add_control(ac->req,
1893 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID,
1895 if (ret != LDB_SUCCESS) {
1904 * This function is called on LDB modify operations. It performs some additions/
1905 * replaces on the current LDB message when "userAccountControl" changes.
1907 static int samldb_user_account_control_change(struct samldb_ctx *ac)
1909 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1915 uint32_t old_uac_computed;
1921 NTTIME old_lockoutTime;
1922 struct ldb_message_element *el;
1923 struct ldb_val *val;
1924 struct ldb_val computer_val;
1925 struct ldb_message *tmp_msg;
1926 struct dom_sid *sid;
1928 struct ldb_result *res;
1929 const char * const attrs[] = {
1931 "isCriticalSystemObject",
1932 "userAccountControl",
1933 "msDS-User-Account-Control-Computed",
1938 bool is_computer = false;
1939 bool old_is_critical = false;
1940 bool new_is_critical = false;
1942 el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
1943 ac->req->operation);
1944 if (el == NULL || el->num_values == 0) {
1945 ldb_asprintf_errstring(ldb,
1946 "%08X: samldb: 'userAccountControl' can't be deleted!",
1947 W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
1948 return LDB_ERR_UNWILLING_TO_PERFORM;
1951 /* Create a temporary message for fetching the "userAccountControl" */
1952 tmp_msg = ldb_msg_new(ac->msg);
1953 if (tmp_msg == NULL) {
1954 return ldb_module_oom(ac->module);
1956 ret = ldb_msg_add(tmp_msg, el, 0);
1957 if (ret != LDB_SUCCESS) {
1960 raw_uac = ldb_msg_find_attr_as_uint(tmp_msg,
1961 "userAccountControl",
1963 talloc_free(tmp_msg);
1965 * UF_LOCKOUT, UF_PASSWD_CANT_CHANGE and UF_PASSWORD_EXPIRED
1966 * are only generated and not stored. We ignore them almost
1967 * completely, along with unknown bits and UF_SCRIPT.
1969 * The only exception is ACB_AUTOLOCK, which features in
1970 * clear_acb when the bit is cleared in this modify operation.
1972 * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are
1973 * ignored by clients and servers
1975 new_uac = raw_uac & UF_SETTABLE_BITS;
1977 /* Fetch the old "userAccountControl" and "objectClass" */
1978 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1979 DSDB_FLAG_NEXT_MODULE, ac->req);
1980 if (ret != LDB_SUCCESS) {
1983 old_uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1985 return ldb_operr(ldb);
1987 old_uac_computed = ldb_msg_find_attr_as_uint(res->msgs[0],
1988 "msDS-User-Account-Control-Computed", 0);
1989 old_lockoutTime = ldb_msg_find_attr_as_int64(res->msgs[0],
1991 old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0],
1992 "isCriticalSystemObject", 0);
1993 /* When we do not have objectclass "computer" we cannot switch to a (read-only) DC */
1994 el = ldb_msg_find_element(res->msgs[0], "objectClass");
1996 return ldb_operr(ldb);
1998 computer_val = data_blob_string_const("computer");
1999 val = ldb_msg_find_val(el, &computer_val);
2004 old_ufa = old_uac & UF_ACCOUNT_TYPE_MASK;
2005 old_atype = ds_uf2atype(old_ufa);
2006 old_pgrid = ds_uf2prim_group_rid(old_uac);
2008 new_ufa = new_uac & UF_ACCOUNT_TYPE_MASK;
2011 * "userAccountControl" = 0 or missing one of the
2012 * types means "UF_NORMAL_ACCOUNT". See MS-SAMR
2013 * 3.1.1.8.10 point 8
2015 new_ufa = UF_NORMAL_ACCOUNT;
2018 sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
2020 return ldb_module_operr(ac->module);
2023 ret = samldb_check_user_account_control_rules(ac, sid,
2027 if (ret != LDB_SUCCESS) {
2031 new_atype = ds_uf2atype(new_ufa);
2032 new_pgrid = ds_uf2prim_group_rid(new_uac);
2034 clear_uac = (old_uac | old_uac_computed) & ~raw_uac;
2037 case UF_NORMAL_ACCOUNT:
2038 new_is_critical = old_is_critical;
2041 case UF_INTERDOMAIN_TRUST_ACCOUNT:
2042 new_is_critical = true;
2045 case UF_WORKSTATION_TRUST_ACCOUNT:
2046 new_is_critical = false;
2047 if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) {
2049 ldb_asprintf_errstring(ldb,
2050 "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT "
2051 "requires objectclass 'computer'!",
2052 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2053 return LDB_ERR_UNWILLING_TO_PERFORM;
2055 new_is_critical = true;
2059 case UF_SERVER_TRUST_ACCOUNT:
2061 ldb_asprintf_errstring(ldb,
2062 "%08X: samldb: UF_SERVER_TRUST_ACCOUNT "
2063 "requires objectclass 'computer'!",
2064 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2065 return LDB_ERR_UNWILLING_TO_PERFORM;
2067 new_is_critical = true;
2071 ldb_asprintf_errstring(ldb,
2072 "%08X: samldb: invalid userAccountControl[0x%08X]",
2073 W_ERROR_V(WERR_INVALID_PARAMETER), raw_uac);
2074 return LDB_ERR_OTHER;
2077 if (old_atype != new_atype) {
2078 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2079 "sAMAccountType", new_atype);
2080 if (ret != LDB_SUCCESS) {
2083 el = ldb_msg_find_element(ac->msg, "sAMAccountType");
2084 el->flags = LDB_FLAG_MOD_REPLACE;
2087 /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */
2088 if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) {
2089 /* "pwdLastSet" reset as password expiration has been forced */
2090 ldb_msg_remove_attr(ac->msg, "lockoutTime");
2091 ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime",
2093 if (ret != LDB_SUCCESS) {
2096 el = ldb_msg_find_element(ac->msg, "lockoutTime");
2097 el->flags = LDB_FLAG_MOD_REPLACE;
2100 /* "isCriticalSystemObject" might be set/changed */
2101 if (old_is_critical != new_is_critical) {
2102 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
2103 new_is_critical ? "TRUE": "FALSE");
2104 if (ret != LDB_SUCCESS) {
2107 el = ldb_msg_find_element(ac->msg,
2108 "isCriticalSystemObject");
2109 el->flags = LDB_FLAG_MOD_REPLACE;
2112 if (!ldb_msg_find_element(ac->msg, "primaryGroupID") &&
2113 (old_pgrid != new_pgrid)) {
2114 /* Older AD deployments don't know about the RODC group */
2115 if (new_pgrid == DOMAIN_RID_READONLY_DCS) {
2116 ret = samldb_prim_group_tester(ac, new_pgrid);
2117 if (ret != LDB_SUCCESS) {
2122 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2123 "primaryGroupID", new_pgrid);
2124 if (ret != LDB_SUCCESS) {
2127 el = ldb_msg_find_element(ac->msg,
2129 el->flags = LDB_FLAG_MOD_REPLACE;
2132 /* Propagate eventual "userAccountControl" attribute changes */
2133 if (old_uac != new_uac) {
2134 char *tempstr = talloc_asprintf(ac->msg, "%d",
2136 if (tempstr == NULL) {
2137 return ldb_module_oom(ac->module);
2140 /* Overwrite "userAccountControl" correctly */
2141 el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
2142 ac->req->operation);
2143 el->values[0].data = (uint8_t *) tempstr;
2144 el->values[0].length = strlen(tempstr);
2146 ldb_msg_remove_attr(ac->msg, "userAccountControl");
2152 static int samldb_lockout_time(struct samldb_ctx *ac)
2154 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2156 struct ldb_message_element *el;
2157 struct ldb_message *tmp_msg;
2160 el = dsdb_get_single_valued_attr(ac->msg, "lockoutTime",
2161 ac->req->operation);
2162 if (el == NULL || el->num_values == 0) {
2163 ldb_asprintf_errstring(ldb,
2164 "%08X: samldb: 'lockoutTime' can't be deleted!",
2165 W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
2166 return LDB_ERR_UNWILLING_TO_PERFORM;
2169 /* Create a temporary message for fetching the "lockoutTime" */
2170 tmp_msg = ldb_msg_new(ac->msg);
2171 if (tmp_msg == NULL) {
2172 return ldb_module_oom(ac->module);
2174 ret = ldb_msg_add(tmp_msg, el, 0);
2175 if (ret != LDB_SUCCESS) {
2178 lockoutTime = ldb_msg_find_attr_as_int64(tmp_msg,
2181 talloc_free(tmp_msg);
2183 if (lockoutTime != 0) {
2187 /* lockoutTime == 0 resets badPwdCount */
2188 ldb_msg_remove_attr(ac->msg, "badPwdCount");
2189 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg,
2191 if (ret != LDB_SUCCESS) {
2194 el = ldb_msg_find_element(ac->msg, "badPwdCount");
2195 el->flags = LDB_FLAG_MOD_REPLACE;
2200 static int samldb_group_type_change(struct samldb_ctx *ac)
2202 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2203 uint32_t group_type, old_group_type, account_type;
2204 struct ldb_message_element *el;
2205 struct ldb_message *tmp_msg;
2207 struct ldb_result *res;
2208 const char * const attrs[] = { "groupType", NULL };
2210 el = dsdb_get_single_valued_attr(ac->msg, "groupType",
2211 ac->req->operation);
2213 /* we are not affected */
2217 /* Create a temporary message for fetching the "groupType" */
2218 tmp_msg = ldb_msg_new(ac->msg);
2219 if (tmp_msg == NULL) {
2220 return ldb_module_oom(ac->module);
2222 ret = ldb_msg_add(tmp_msg, el, 0);
2223 if (ret != LDB_SUCCESS) {
2226 group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
2227 talloc_free(tmp_msg);
2229 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
2230 DSDB_FLAG_NEXT_MODULE |
2231 DSDB_SEARCH_SHOW_DELETED, ac->req);
2232 if (ret != LDB_SUCCESS) {
2235 old_group_type = ldb_msg_find_attr_as_uint(res->msgs[0], "groupType", 0);
2236 if (old_group_type == 0) {
2237 return ldb_operr(ldb);
2240 /* Group type switching isn't so easy as it seems: We can only
2241 * change in this directions: global <-> universal <-> local
2242 * On each step also the group type itself
2243 * (security/distribution) is variable. */
2245 if (ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID) == NULL) {
2246 switch (group_type) {
2247 case GTYPE_SECURITY_GLOBAL_GROUP:
2248 case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
2249 /* change to "universal" allowed */
2250 if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
2251 (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
2252 ldb_set_errstring(ldb,
2253 "samldb: Change from security/distribution local group forbidden!");
2254 return LDB_ERR_UNWILLING_TO_PERFORM;
2258 case GTYPE_SECURITY_UNIVERSAL_GROUP:
2259 case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
2260 /* each change allowed */
2262 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
2263 case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
2264 /* change to "universal" allowed */
2265 if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
2266 (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
2267 ldb_set_errstring(ldb,
2268 "samldb: Change from security/distribution global group forbidden!");
2269 return LDB_ERR_UNWILLING_TO_PERFORM;
2273 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
2275 /* we don't allow this "groupType" values */
2276 return LDB_ERR_UNWILLING_TO_PERFORM;
2281 account_type = ds_gtype2atype(group_type);
2282 if (account_type == 0) {
2283 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
2284 return LDB_ERR_UNWILLING_TO_PERFORM;
2286 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
2288 if (ret != LDB_SUCCESS) {
2291 el = ldb_msg_find_element(ac->msg, "sAMAccountType");
2292 el->flags = LDB_FLAG_MOD_REPLACE;
2297 static int samldb_member_check(struct samldb_ctx *ac)
2299 const char * const attrs[] = { "objectSid", NULL };
2300 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2301 struct ldb_message_element *el;
2302 struct ldb_dn *member_dn;
2303 struct dom_sid *sid;
2304 struct ldb_result *res;
2305 struct dom_sid *group_sid;
2309 /* Fetch information from the existing object */
2311 ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
2312 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req, NULL);
2313 if (ret != LDB_SUCCESS) {
2316 if (res->count != 1) {
2317 return ldb_operr(ldb);
2320 group_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
2321 if (group_sid == NULL) {
2322 return ldb_operr(ldb);
2325 /* We've to walk over all modification entries and consider the "member"
2327 for (i = 0; i < ac->msg->num_elements; i++) {
2328 if (ldb_attr_cmp(ac->msg->elements[i].name, "member") != 0) {
2332 el = &ac->msg->elements[i];
2333 for (j = 0; j < el->num_values; j++) {
2334 struct ldb_result *group_res;
2335 const char *group_attrs[] = { "primaryGroupID" , NULL };
2336 uint32_t prim_group_rid;
2338 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
2339 /* Deletes will be handled in
2340 * repl_meta_data, and deletes not
2341 * matching a member will return
2342 * LDB_ERR_UNWILLING_TO_PERFORM
2347 member_dn = ldb_dn_from_ldb_val(ac, ldb,
2349 if (!ldb_dn_validate(member_dn)) {
2350 return ldb_operr(ldb);
2353 /* Denies to add "member"s to groups which are primary
2354 * ones for them - in this case return
2355 * ERR_ENTRY_ALREADY_EXISTS. */
2357 ret = dsdb_module_search_dn(ac->module, ac, &group_res,
2358 member_dn, group_attrs,
2359 DSDB_FLAG_NEXT_MODULE, ac->req);
2360 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2361 /* member DN doesn't exist yet */
2364 if (ret != LDB_SUCCESS) {
2367 prim_group_rid = ldb_msg_find_attr_as_uint(group_res->msgs[0], "primaryGroupID", (uint32_t)-1);
2368 if (prim_group_rid == (uint32_t) -1) {
2369 /* the member hasn't to be a user account ->
2370 * therefore no check needed in this case. */
2374 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
2377 return ldb_operr(ldb);
2380 if (dom_sid_equal(group_sid, sid)) {
2381 ldb_asprintf_errstring(ldb,
2382 "samldb: member %s already set via primaryGroupID %u",
2383 ldb_dn_get_linearized(member_dn), prim_group_rid);
2384 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2394 /* SAM objects have special rules regarding the "description" attribute on
2395 * modify operations. */
2396 static int samldb_description_check(struct samldb_ctx *ac, bool *modified)
2398 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2399 const char * const attrs[] = { "objectClass", "description", NULL };
2400 struct ldb_result *res;
2404 /* Fetch information from the existing object */
2405 ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
2406 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req,
2407 "(|(objectclass=user)(objectclass=group)(objectclass=samDomain)(objectclass=samServer))");
2408 if (ret != LDB_SUCCESS) {
2409 /* don't treat it specially ... let normal error codes
2410 happen from other places */
2411 ldb_reset_err_string(ldb);
2414 if (res->count == 0) {
2415 /* we didn't match the filter */
2420 /* We've to walk over all modification entries and consider the
2421 * "description" ones. */
2422 for (i = 0; i < ac->msg->num_elements; i++) {
2423 if (ldb_attr_cmp(ac->msg->elements[i].name, "description") == 0) {
2424 ac->msg->elements[i].flags |= LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK;
2434 /* This trigger adapts the "servicePrincipalName" attributes if the
2435 * "dNSHostName" and/or "sAMAccountName" attribute change(s) */
2436 static int samldb_service_principal_names_change(struct samldb_ctx *ac)
2438 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2439 struct ldb_message_element *el = NULL, *el2 = NULL;
2440 struct ldb_message *msg;
2441 const char * const attrs[] = { "servicePrincipalName", NULL };
2442 struct ldb_result *res;
2443 const char *dns_hostname = NULL, *old_dns_hostname = NULL,
2444 *sam_accountname = NULL, *old_sam_accountname = NULL;
2448 el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName",
2449 ac->req->operation);
2450 el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
2451 ac->req->operation);
2452 if ((el == NULL) && (el2 == NULL)) {
2453 /* we are not affected */
2457 /* Create a temporary message for fetching the "dNSHostName" */
2459 const char *dns_attrs[] = { "dNSHostName", NULL };
2460 msg = ldb_msg_new(ac->msg);
2462 return ldb_module_oom(ac->module);
2464 ret = ldb_msg_add(msg, el, 0);
2465 if (ret != LDB_SUCCESS) {
2468 dns_hostname = talloc_strdup(ac,
2469 ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL));
2470 if (dns_hostname == NULL) {
2471 return ldb_module_oom(ac->module);
2476 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn,
2477 dns_attrs, DSDB_FLAG_NEXT_MODULE, ac->req);
2478 if (ret == LDB_SUCCESS) {
2479 old_dns_hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
2483 /* Create a temporary message for fetching the "sAMAccountName" */
2485 char *tempstr, *tempstr2 = NULL;
2486 const char *acct_attrs[] = { "sAMAccountName", NULL };
2488 msg = ldb_msg_new(ac->msg);
2490 return ldb_module_oom(ac->module);
2492 ret = ldb_msg_add(msg, el2, 0);
2493 if (ret != LDB_SUCCESS) {
2496 tempstr = talloc_strdup(ac,
2497 ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL));
2500 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, acct_attrs,
2501 DSDB_FLAG_NEXT_MODULE, ac->req);
2502 if (ret == LDB_SUCCESS) {
2503 tempstr2 = talloc_strdup(ac,
2504 ldb_msg_find_attr_as_string(res->msgs[0],
2505 "sAMAccountName", NULL));
2509 /* The "sAMAccountName" needs some additional trimming: we need
2510 * to remove the trailing "$"s if they exist. */
2511 if ((tempstr != NULL) && (tempstr[0] != '\0') &&
2512 (tempstr[strlen(tempstr) - 1] == '$')) {
2513 tempstr[strlen(tempstr) - 1] = '\0';
2515 if ((tempstr2 != NULL) && (tempstr2[0] != '\0') &&
2516 (tempstr2[strlen(tempstr2) - 1] == '$')) {
2517 tempstr2[strlen(tempstr2) - 1] = '\0';
2519 sam_accountname = tempstr;
2520 old_sam_accountname = tempstr2;
2523 if (old_dns_hostname == NULL) {
2524 /* we cannot change when the old name is unknown */
2525 dns_hostname = NULL;
2527 if ((old_dns_hostname != NULL) && (dns_hostname != NULL) &&
2528 (strcasecmp_m(old_dns_hostname, dns_hostname) == 0)) {
2529 /* The "dNSHostName" didn't change */
2530 dns_hostname = NULL;
2533 if (old_sam_accountname == NULL) {
2534 /* we cannot change when the old name is unknown */
2535 sam_accountname = NULL;
2537 if ((old_sam_accountname != NULL) && (sam_accountname != NULL) &&
2538 (strcasecmp_m(old_sam_accountname, sam_accountname) == 0)) {
2539 /* The "sAMAccountName" didn't change */
2540 sam_accountname = NULL;
2543 if ((dns_hostname == NULL) && (sam_accountname == NULL)) {
2544 /* Well, there are information missing (old name(s)) or the
2545 * names didn't change. We've nothing to do and can exit here */
2549 /* Potential "servicePrincipalName" changes in the same request have to
2550 * be handled before the update (Windows behaviour). */
2551 el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
2553 msg = ldb_msg_new(ac->msg);
2555 return ldb_module_oom(ac->module);
2557 msg->dn = ac->msg->dn;
2560 ret = ldb_msg_add(msg, el, el->flags);
2561 if (ret != LDB_SUCCESS) {
2565 ldb_msg_remove_element(ac->msg, el);
2567 el = ldb_msg_find_element(ac->msg,
2568 "servicePrincipalName");
2569 } while (el != NULL);
2571 ret = dsdb_module_modify(ac->module, msg,
2572 DSDB_FLAG_NEXT_MODULE, ac->req);
2573 if (ret != LDB_SUCCESS) {
2579 /* Fetch the "servicePrincipalName"s if any */
2580 ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
2581 DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
2582 if (ret != LDB_SUCCESS) {
2585 if ((res->count != 1) || (res->msgs[0]->num_elements > 1)) {
2586 return ldb_operr(ldb);
2589 if (res->msgs[0]->num_elements == 1) {
2591 * Yes, we do have "servicePrincipalName"s. First we update them
2592 * locally, that means we do always substitute the current
2593 * "dNSHostName" with the new one and/or "sAMAccountName"
2594 * without "$" with the new one and then we append the
2595 * modified "servicePrincipalName"s as a message element
2596 * replace to the modification request (Windows behaviour). We
2597 * need also to make sure that the values remain case-
2598 * insensitively unique.
2601 ret = ldb_msg_add_empty(ac->msg, "servicePrincipalName",
2602 LDB_FLAG_MOD_REPLACE, &el);
2603 if (ret != LDB_SUCCESS) {
2607 for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) {
2608 char *old_str, *new_str;
2611 struct ldb_val *vals;
2615 res->msgs[0]->elements[0].values[i].data;
2617 new_str = talloc_strdup(ac->msg,
2618 strtok_r(old_str, "/", &pos));
2619 if (new_str == NULL) {
2620 return ldb_module_oom(ac->module);
2623 while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
2624 if ((dns_hostname != NULL) &&
2625 (strcasecmp_m(tok, old_dns_hostname) == 0)) {
2628 if ((sam_accountname != NULL) &&
2629 (strcasecmp_m(tok, old_sam_accountname) == 0)) {
2630 tok = sam_accountname;
2633 new_str = talloc_asprintf(ac->msg, "%s/%s",
2635 if (new_str == NULL) {
2636 return ldb_module_oom(ac->module);
2640 /* Uniqueness check */
2641 for (j = 0; (!found) && (j < el->num_values); j++) {
2642 if (strcasecmp_m((char *)el->values[j].data,
2652 * append the new "servicePrincipalName" -
2653 * code derived from ldb_msg_add_value().
2655 * Open coded to make it clear that we must
2656 * append to the MOD_REPLACE el created above.
2658 vals = talloc_realloc(ac->msg, el->values,
2660 el->num_values + 1);
2662 return ldb_module_oom(ac->module);
2665 el->values[el->num_values] = data_blob_string_const(new_str);
2675 /* This checks the "fSMORoleOwner" attributes */
2676 static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac)
2678 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2679 const char * const no_attrs[] = { NULL };
2680 struct ldb_message_element *el;
2681 struct ldb_message *tmp_msg;
2682 struct ldb_dn *res_dn;
2683 struct ldb_result *res;
2686 el = dsdb_get_single_valued_attr(ac->msg, "fSMORoleOwner",
2687 ac->req->operation);
2689 /* we are not affected */
2693 /* Create a temporary message for fetching the "fSMORoleOwner" */
2694 tmp_msg = ldb_msg_new(ac->msg);
2695 if (tmp_msg == NULL) {
2696 return ldb_module_oom(ac->module);
2698 ret = ldb_msg_add(tmp_msg, el, 0);
2699 if (ret != LDB_SUCCESS) {
2702 res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner");
2703 talloc_free(tmp_msg);
2705 if (res_dn == NULL) {
2706 ldb_set_errstring(ldb,
2707 "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
2708 if (ac->req->operation == LDB_ADD) {
2709 return LDB_ERR_CONSTRAINT_VIOLATION;
2711 return LDB_ERR_UNWILLING_TO_PERFORM;
2715 /* Fetched DN has to reference a "nTDSDSA" entry */
2716 ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE,
2718 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
2719 ac->req, "(objectClass=nTDSDSA)");
2720 if (ret != LDB_SUCCESS) {
2723 if (res->count != 1) {
2724 ldb_set_errstring(ldb,
2725 "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
2726 return LDB_ERR_UNWILLING_TO_PERFORM;
2735 * Return zero if the number of zero bits in the address (looking from low to
2736 * high) is equal to or greater than the length minus the mask. Otherwise it
2739 static int check_cidr_zero_bits(uint8_t *address, unsigned int len,
2742 /* <address> is an integer in big-endian form, <len> bits long. All
2743 bits between <mask> and <len> must be zero. */
2745 unsigned int byte_len;
2746 unsigned int byte_mask;
2747 unsigned int bit_mask;
2749 DBG_INFO("Looking at address %02x%02x%02x%02x, mask %u\n",
2750 address[0], address[1], address[2], address[3],
2752 } else if (len == 128){
2753 DBG_INFO("Looking at address "
2754 "%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
2755 "%02x%02x-%02x%02x-%02x%02x-%02x%02x, mask %u\n",
2756 address[0], address[1], address[2], address[3],
2757 address[4], address[5], address[6], address[7],
2758 address[8], address[9], address[10], address[11],
2759 address[12], address[13], address[14], address[15],
2764 DBG_INFO("mask %u is too big (> %u)\n", mask, len);
2768 /* single address subnet.
2769 * In IPv4 all 255s is invalid by the bitmask != address rule
2770 * in MS-ADTS. IPv6 does not suffer.
2773 if (address[0] == 255 &&
2774 address[1] == 255 &&
2775 address[2] == 255 &&
2784 byte_mask = mask / 8;
2786 for (i = byte_len - 1; i > byte_mask; i--){
2787 DBG_DEBUG("checking byte %d %02x\n", i, address[i]);
2788 if (address[i] != 0){
2792 bit_mask = (1 << (8 - (mask & 7))) - 1;
2793 DBG_DEBUG("checking bitmask %02x & %02x overlap %02x\n", bit_mask, address[byte_mask],
2794 bit_mask & address[byte_mask]);
2795 if (address[byte_mask] & bit_mask){
2799 /* According to MS-ADTS, the mask can't exactly equal the bitmask for
2800 * IPv4 (but this is fine for v6). That is 255.255.80.0/17 is bad,
2801 * because the bitmask implied by "/17" is 255.255.80.0.
2803 * The bit_mask used in the previous check is the complement of what
2806 if (len == 32 && address[byte_mask] == (uint8_t)~bit_mask){
2808 for (i = 0; i < byte_mask; i++){
2809 if (address[i] != 255){
2823 static int check_address_roundtrip(const char *address, int family,
2824 const uint8_t *address_bytes,
2825 char *buffer, int buffer_len)
2828 * Check that the address is in the canonical RFC5952 format for IPv6,
2829 * and lacks extra leading zeros for each dotted decimal for IPv4.
2830 * Handily this is what inet_ntop() gives you.
2832 const char *address_redux = inet_ntop(family, address_bytes,
2833 buffer, buffer_len);
2834 if (address_redux == NULL){
2835 DBG_INFO("Address round trip %s failed unexpectedly"
2836 " with errno %d\n", address, errno);
2839 if (strcasecmp(address, address_redux) != 0){
2840 DBG_INFO("Address %s round trips to %s; fail!\n",
2841 address, address_redux);
2842 /* If the address family is IPv6, and the address is in a
2846 if (strchr(address_redux, '.') != NULL){
2847 DEBUG(0, ("The IPv6 address '%s' has the misfortune of "
2848 "lying in a range that was once used for "
2849 "IPv4 embedding (that is, it might also be "
2850 "represented as '%s').\n", address,
2861 * MS-ADTS v20150630 6.1.1.2.2.2.1 Subnet Object, refers to RFC1166 and
2862 * RFC2373. It specifies something seemingly indistinguishable from an RFC4632
2863 * CIDR address range without saying so explicitly. Here we follow the CIDR
2866 * Return 0 on success, -1 on error.
2868 static int verify_cidr(const char *cidr)
2870 char *address = NULL, *slash = NULL, *endptr = NULL;
2871 bool has_colon, has_dot;
2874 uint8_t *address_bytes = NULL;
2875 char *address_redux = NULL;
2876 unsigned int address_len;
2877 TALLOC_CTX *frame = NULL;
2879 DBG_DEBUG("CIDR is %s\n", cidr);
2880 frame = talloc_stackframe();
2881 address = talloc_strdup(frame, cidr);
2882 if (address == NULL){
2886 /* there must be a '/' */
2887 slash = strchr(address, '/');
2891 /* terminate the address for strchr, inet_pton */
2894 mask = strtoul(slash + 1, &endptr, 10);
2896 DBG_INFO("Windows does not like the zero mask, "
2897 "so nor do we: %s\n", cidr);
2901 if (*endptr != '\0' || endptr == slash + 1){
2902 DBG_INFO("CIDR mask is not a proper integer: %s\n", cidr);
2906 address_bytes = talloc_size(frame, sizeof(struct in6_addr));
2907 if (address_bytes == NULL){
2911 address_redux = talloc_size(frame, INET6_ADDRSTRLEN);
2912 if (address_redux == NULL){
2916 DBG_INFO("found address %s, mask %lu\n", address, mask);
2917 has_colon = (strchr(address, ':') == NULL) ? false : true;
2918 has_dot = (strchr(address, '.') == NULL) ? false : true;
2919 if (has_dot && has_colon){
2920 /* This seems to be an IPv4 address embedded in IPv6, which is
2921 icky. We don't support it. */
2922 DBG_INFO("Refusing to consider cidr '%s' with dots and colons\n",
2925 } else if (has_colon){ /* looks like IPv6 */
2926 res = inet_pton(AF_INET6, address, address_bytes);
2928 DBG_INFO("Address in %s fails to parse as IPv6\n", cidr);
2932 if (check_address_roundtrip(address, AF_INET6, address_bytes,
2933 address_redux, INET6_ADDRSTRLEN)){
2936 } else if (has_dot) {
2937 /* looks like IPv4 */
2938 if (strcmp(address, "0.0.0.0") == 0){
2939 DBG_INFO("Windows does not like the zero IPv4 address, "
2943 res = inet_pton(AF_INET, address, address_bytes);
2945 DBG_INFO("Address in %s fails to parse as IPv4\n", cidr);
2950 if (check_address_roundtrip(address, AF_INET, address_bytes,
2951 address_redux, INET_ADDRSTRLEN)){
2955 /* This doesn't look like an IP address at all. */
2959 ret = check_cidr_zero_bits(address_bytes, address_len, mask);
2968 static int samldb_verify_subnet(struct samldb_ctx *ac)
2970 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2971 const char *cidr = NULL;
2972 const struct ldb_val *rdn_value = NULL;
2974 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
2975 if (rdn_value == NULL) {
2976 ldb_set_errstring(ldb, "samldb: ldb_dn_get_rdn_val "
2978 return LDB_ERR_UNWILLING_TO_PERFORM;
2981 cidr = ldb_dn_escape_value(ac, *rdn_value);
2982 DBG_INFO("looking at cidr '%s'\n", cidr);
2984 ldb_set_errstring(ldb,
2985 "samldb: adding an empty subnet cidr seems wrong");
2986 return LDB_ERR_UNWILLING_TO_PERFORM;
2989 if (verify_cidr(cidr)){
2990 ldb_set_errstring(ldb,
2991 "samldb: subnet value is invalid");
2992 return LDB_ERR_INVALID_DN_SYNTAX;
3000 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
3002 struct ldb_context *ldb;
3003 struct samldb_ctx *ac;
3004 struct ldb_message_element *el;
3007 ldb = ldb_module_get_ctx(module);
3008 ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
3010 /* do not manipulate our control entries */
3011 if (ldb_dn_is_special(req->op.add.message->dn)) {
3012 return ldb_next_request(module, req);
3015 el = ldb_msg_find_element(req->op.add.message, "userParameters");
3016 if (el != NULL && ldb_req_is_untrusted(req)) {
3017 const char *reason = "samldb_add: "
3018 "setting userParameters is not supported over LDAP, "
3019 "see https://bugzilla.samba.org/show_bug.cgi?id=8077";
3020 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason);
3021 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason);
3024 ac = samldb_ctx_init(module, req);
3026 return ldb_operr(ldb);
3029 /* build the new msg */
3030 ac->msg = ldb_msg_copy_shallow(ac, req->op.add.message);
3031 if (ac->msg == NULL) {
3033 ldb_debug(ldb, LDB_DEBUG_FATAL,
3034 "samldb_add: ldb_msg_copy_shallow failed!\n");
3035 return ldb_operr(ldb);
3038 el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
3040 ret = samldb_fsmo_role_owner_check(ac);
3041 if (ret != LDB_SUCCESS) {
3046 if (samdb_find_attribute(ldb, ac->msg,
3047 "objectclass", "user") != NULL) {
3048 ac->type = SAMLDB_TYPE_USER;
3050 ret = samldb_prim_group_trigger(ac);
3051 if (ret != LDB_SUCCESS) {
3055 ret = samldb_objectclass_trigger(ac);
3056 if (ret != LDB_SUCCESS) {
3060 return samldb_fill_object(ac);
3063 if (samdb_find_attribute(ldb, ac->msg,
3064 "objectclass", "group") != NULL) {
3065 ac->type = SAMLDB_TYPE_GROUP;
3067 ret = samldb_objectclass_trigger(ac);
3068 if (ret != LDB_SUCCESS) {
3072 return samldb_fill_object(ac);
3075 /* perhaps a foreignSecurityPrincipal? */
3076 if (samdb_find_attribute(ldb, ac->msg,
3078 "foreignSecurityPrincipal") != NULL) {
3079 return samldb_fill_foreignSecurityPrincipal_object(ac);
3082 if (samdb_find_attribute(ldb, ac->msg,
3083 "objectclass", "classSchema") != NULL) {
3084 ac->type = SAMLDB_TYPE_CLASS;
3086 ret = samldb_schema_governsid_valid_check(ac);
3087 if (ret != LDB_SUCCESS) {
3091 ret = samldb_schema_ldapdisplayname_valid_check(ac);
3092 if (ret != LDB_SUCCESS) {
3096 ret = samldb_schema_info_update(ac);
3097 if (ret != LDB_SUCCESS) {
3102 return samldb_fill_object(ac);
3105 if (samdb_find_attribute(ldb, ac->msg,
3106 "objectclass", "attributeSchema") != NULL) {
3107 ac->type = SAMLDB_TYPE_ATTRIBUTE;
3109 ret = samldb_schema_attributeid_valid_check(ac);
3110 if (ret != LDB_SUCCESS) {
3114 ret = samldb_schema_ldapdisplayname_valid_check(ac);
3115 if (ret != LDB_SUCCESS) {
3119 ret = samldb_schema_info_update(ac);
3120 if (ret != LDB_SUCCESS) {
3125 return samldb_fill_object(ac);
3128 if (samdb_find_attribute(ldb, ac->msg,
3129 "objectclass", "subnet") != NULL) {
3130 ret = samldb_verify_subnet(ac);
3131 if (ret != LDB_SUCCESS) {
3135 /* We are just checking the value is valid, and there are no
3136 values to fill in. */
3141 /* nothing matched, go on */
3142 return ldb_next_request(module, req);
3146 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
3148 struct ldb_context *ldb;
3149 struct samldb_ctx *ac;
3150 struct ldb_message_element *el, *el2;
3151 struct ldb_control *is_undelete;
3152 bool modified = false;
3155 if (ldb_dn_is_special(req->op.mod.message->dn)) {
3156 /* do not manipulate our control entries */
3157 return ldb_next_request(module, req);
3160 ldb = ldb_module_get_ctx(module);
3163 * we are going to need some special handling if in Undelete call.
3164 * Since tombstone_reanimate module will restore certain attributes,
3165 * we need to relax checks for: sAMAccountType, primaryGroupID
3167 is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
3169 /* make sure that "objectSid" is not specified */
3170 el = ldb_msg_find_element(req->op.mod.message, "objectSid");
3172 if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) {
3173 ldb_set_errstring(ldb,
3174 "samldb: objectSid must not be specified!");
3175 return LDB_ERR_UNWILLING_TO_PERFORM;
3178 if (is_undelete == NULL) {
3179 /* make sure that "sAMAccountType" is not specified */
3180 el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType");
3182 ldb_set_errstring(ldb,
3183 "samldb: sAMAccountType must not be specified!");
3184 return LDB_ERR_UNWILLING_TO_PERFORM;
3187 /* make sure that "isCriticalSystemObject" is not specified */
3188 el = ldb_msg_find_element(req->op.mod.message, "isCriticalSystemObject");
3190 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) == NULL) {
3191 ldb_set_errstring(ldb,
3192 "samldb: isCriticalSystemObject must not be specified!");
3193 return LDB_ERR_UNWILLING_TO_PERFORM;
3197 /* msDS-IntId is not allowed to be modified
3198 * except when modification comes from replication */
3199 if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
3200 if (!ldb_request_get_control(req,
3201 DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
3202 return LDB_ERR_CONSTRAINT_VIOLATION;
3206 el = ldb_msg_find_element(req->op.mod.message, "userParameters");
3207 if (el != NULL && ldb_req_is_untrusted(req)) {
3208 const char *reason = "samldb: "
3209 "setting userParameters is not supported over LDAP, "
3210 "see https://bugzilla.samba.org/show_bug.cgi?id=8077";
3211 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason);
3212 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason);
3215 ac = samldb_ctx_init(module, req);
3217 return ldb_operr(ldb);
3220 /* build the new msg */
3221 ac->msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
3222 if (ac->msg == NULL) {
3224 ldb_debug(ldb, LDB_DEBUG_FATAL,
3225 "samldb_modify: ldb_msg_copy_shallow failed!\n");
3226 return ldb_operr(ldb);
3229 if (is_undelete == NULL) {
3230 el = ldb_msg_find_element(ac->msg, "primaryGroupID");
3232 ret = samldb_prim_group_trigger(ac);
3233 if (ret != LDB_SUCCESS) {
3239 el = ldb_msg_find_element(ac->msg, "userAccountControl");
3242 ret = samldb_user_account_control_change(ac);
3243 if (ret != LDB_SUCCESS) {
3248 el = ldb_msg_find_element(ac->msg, "lockoutTime");
3251 ret = samldb_lockout_time(ac);
3252 if (ret != LDB_SUCCESS) {
3257 el = ldb_msg_find_element(ac->msg, "groupType");
3260 ret = samldb_group_type_change(ac);
3261 if (ret != LDB_SUCCESS) {
3266 el = ldb_msg_find_element(ac->msg, "sAMAccountName");
3268 ret = samldb_sam_accountname_valid_check(ac);
3270 * Other errors are checked for elsewhere, we just
3271 * want to prevent duplicates
3273 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
3278 el = ldb_msg_find_element(ac->msg, "ldapDisplayName");
3280 ret = samldb_schema_ldapdisplayname_valid_check(ac);
3281 if (ret != LDB_SUCCESS) {
3286 el = ldb_msg_find_element(ac->msg, "attributeID");
3288 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
3289 "Once set, attributeID values may not be modified");
3290 return LDB_ERR_CONSTRAINT_VIOLATION;
3293 el = ldb_msg_find_element(ac->msg, "governsID");
3295 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
3296 "Once set, governsID values may not be modified");
3297 return LDB_ERR_CONSTRAINT_VIOLATION;
3300 el = ldb_msg_find_element(ac->msg, "member");
3302 ret = samldb_member_check(ac);
3303 if (ret != LDB_SUCCESS) {
3308 el = ldb_msg_find_element(ac->msg, "description");
3310 ret = samldb_description_check(ac, &modified);
3311 if (ret != LDB_SUCCESS) {
3316 el = ldb_msg_find_element(ac->msg, "dNSHostName");
3317 el2 = ldb_msg_find_element(ac->msg, "sAMAccountName");
3318 if ((el != NULL) || (el2 != NULL)) {
3320 ret = samldb_service_principal_names_change(ac);
3321 if (ret != LDB_SUCCESS) {
3326 el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
3328 ret = samldb_fsmo_role_owner_check(ac);
3329 if (ret != LDB_SUCCESS) {
3335 struct ldb_request *child_req;
3337 /* Now perform the real modifications as a child request */
3338 ret = ldb_build_mod_req(&child_req, ldb, ac,
3341 req, dsdb_next_callback,
3343 LDB_REQ_SET_LOCATION(child_req);
3344 if (ret != LDB_SUCCESS) {
3348 return ldb_next_request(module, child_req);
3353 /* no change which interests us, go on */
3354 return ldb_next_request(module, req);
3359 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
3361 struct ldb_context *ldb;
3362 struct dom_sid *sid;
3366 struct ldb_result *res;
3367 const char * const attrs[] = { "objectSid", "isDeleted", NULL };
3368 const char * const noattrs[] = { NULL };
3370 ldb = ldb_module_get_ctx(ac->module);
3372 /* Finds out the SID/RID of the SAM object */
3373 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn,
3375 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
3377 if (ret != LDB_SUCCESS) {
3381 if (ldb_msg_check_string_attribute(res->msgs[0], "isDeleted", "TRUE")) {
3385 sid = samdb_result_dom_sid(ac, res->msgs[0], "objectSid");
3387 /* No SID - it might not be a SAM object - therefore ok */
3390 status = dom_sid_split_rid(ac, sid, NULL, &rid);
3391 if (!NT_STATUS_IS_OK(status)) {
3392 return ldb_operr(ldb);
3395 /* Special object (security principal?) */
3398 /* do not allow deletion of well-known sids */
3399 if (rid < DSDB_SAMDB_MINIMUM_ALLOWED_RID &&
3400 (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
3401 return LDB_ERR_OTHER;
3404 /* Deny delete requests from groups which are primary ones */
3405 ret = dsdb_module_search(ac->module, ac, &res,
3406 ldb_get_default_basedn(ldb),
3407 LDB_SCOPE_SUBTREE, noattrs,
3408 DSDB_FLAG_NEXT_MODULE,
3410 "(&(primaryGroupID=%u)(objectClass=user))", rid);
3411 if (ret != LDB_SUCCESS) {
3414 if (res->count > 0) {
3415 return LDB_ERR_ENTRY_ALREADY_EXISTS;
3421 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
3423 struct samldb_ctx *ac;
3426 if (ldb_dn_is_special(req->op.del.dn)) {
3427 /* do not manipulate our control entries */
3428 return ldb_next_request(module, req);
3431 ac = samldb_ctx_init(module, req);
3433 return ldb_operr(ldb_module_get_ctx(module));
3436 ret = samldb_prim_group_users_check(ac);
3437 if (ret != LDB_SUCCESS) {
3443 return ldb_next_request(module, req);
3448 static int check_rename_constraints(struct ldb_message *msg,
3449 struct samldb_ctx *ac,
3450 struct ldb_dn *olddn, struct ldb_dn *newdn)
3452 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3453 struct ldb_dn *dn1, *dn2, *nc_root;
3454 int32_t systemFlags;
3455 bool move_op = false;
3456 bool rename_op = false;
3459 /* Skip the checks if old and new DN are the same, or if we have the
3460 * relax control specified or if the returned objects is already
3461 * deleted and needs only to be moved for consistency. */
3463 if (ldb_dn_compare(olddn, newdn) == 0) {
3466 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) {
3470 if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) {
3472 * check originating request if we are supposed
3473 * to "see" this record in first place.
3475 if (ldb_request_get_control(ac->req, LDB_CONTROL_SHOW_DELETED_OID) == NULL) {
3476 return LDB_ERR_NO_SUCH_OBJECT;
3478 return LDB_ERR_UNWILLING_TO_PERFORM;
3481 /* Objects under CN=System */
3483 dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb));
3484 if (dn1 == NULL) return ldb_oom(ldb);
3486 if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) {
3488 return LDB_ERR_OPERATIONS_ERROR;
3491 if ((ldb_dn_compare_base(dn1, olddn) == 0) &&
3492 (ldb_dn_compare_base(dn1, newdn) != 0)) {
3494 ldb_asprintf_errstring(ldb,
3495 "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!",
3496 ldb_dn_get_linearized(olddn));
3497 return LDB_ERR_OTHER;
3504 if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) ||
3505 (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) {
3506 ldb_asprintf_errstring(ldb,
3507 "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!",
3508 ldb_dn_get_linearized(olddn));
3509 return LDB_ERR_UNWILLING_TO_PERFORM;
3512 /* subnet objects */
3513 if (samdb_find_attribute(ldb, msg, "objectclass", "subnet") != NULL) {
3514 ret = samldb_verify_subnet(ac);
3515 if (ret != LDB_SUCCESS) {
3523 dn1 = ldb_dn_get_parent(ac, olddn);
3524 if (dn1 == NULL) return ldb_oom(ldb);
3525 dn2 = ldb_dn_get_parent(ac, newdn);
3526 if (dn2 == NULL) return ldb_oom(ldb);
3528 if (ldb_dn_compare(dn1, dn2) == 0) {
3537 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
3539 /* Fetch name context */
3541 ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root);
3542 if (ret != LDB_SUCCESS) {
3546 if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
3548 ldb_asprintf_errstring(ldb,
3549 "subtree_rename: Cannot move %s within schema partition",
3550 ldb_dn_get_linearized(olddn));
3551 return LDB_ERR_UNWILLING_TO_PERFORM;
3554 (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) {
3555 ldb_asprintf_errstring(ldb,
3556 "subtree_rename: Cannot rename %s within schema partition",
3557 ldb_dn_get_linearized(olddn));
3558 return LDB_ERR_UNWILLING_TO_PERFORM;
3560 } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
3562 (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) {
3563 /* Here we have to do more: control the
3564 * "ALLOW_LIMITED_MOVE" flag. This means that the
3565 * grand-grand-parents of two objects have to be equal
3566 * in order to perform the move (this is used for
3567 * moving "server" objects in the "sites" container). */
3569 systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE;
3572 dn1 = ldb_dn_copy(ac, olddn);
3573 if (dn1 == NULL) return ldb_oom(ldb);
3574 dn2 = ldb_dn_copy(ac, newdn);
3575 if (dn2 == NULL) return ldb_oom(ldb);
3577 limited_move &= ldb_dn_remove_child_components(dn1, 3);
3578 limited_move &= ldb_dn_remove_child_components(dn2, 3);
3579 limited_move &= ldb_dn_compare(dn1, dn2) == 0;
3586 && ldb_request_get_control(ac->req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID) == NULL) {
3587 ldb_asprintf_errstring(ldb,
3588 "subtree_rename: Cannot move %s to %s in config partition",
3589 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
3590 return LDB_ERR_UNWILLING_TO_PERFORM;
3594 (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) {
3595 ldb_asprintf_errstring(ldb,
3596 "subtree_rename: Cannot rename %s to %s within config partition",
3597 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
3598 return LDB_ERR_UNWILLING_TO_PERFORM;
3600 } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
3602 (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) {
3603 ldb_asprintf_errstring(ldb,
3604 "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set",
3605 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
3606 return LDB_ERR_UNWILLING_TO_PERFORM;
3609 (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) {
3610 ldb_asprintf_errstring(ldb,
3611 "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set",
3612 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
3613 return LDB_ERR_UNWILLING_TO_PERFORM;
3617 talloc_free(nc_root);
3623 static int samldb_rename_search_base_callback(struct ldb_request *req,
3624 struct ldb_reply *ares)
3626 struct samldb_ctx *ac;
3629 ac = talloc_get_type(req->context, struct samldb_ctx);
3632 return ldb_module_done(ac->req, NULL, NULL,
3633 LDB_ERR_OPERATIONS_ERROR);
3635 if (ares->error != LDB_SUCCESS) {
3636 return ldb_module_done(ac->req, ares->controls,
3637 ares->response, ares->error);
3640 switch (ares->type) {
3641 case LDB_REPLY_ENTRY:
3643 * This is the root entry of the originating move
3644 * respectively rename request. It has been already
3645 * stored in the list using "subtree_rename_search()".
3646 * Only this one is subject to constraint checking.
3648 ret = check_rename_constraints(ares->message, ac,
3649 ac->req->op.rename.olddn,
3650 ac->req->op.rename.newdn);
3651 if (ret != LDB_SUCCESS) {
3652 return ldb_module_done(ac->req, NULL, NULL,
3657 case LDB_REPLY_REFERRAL:
3661 case LDB_REPLY_DONE:
3664 * Great, no problem with the rename, so go ahead as
3665 * if we never were here
3667 ret = ldb_next_request(ac->module, ac->req);
3678 static int samldb_rename(struct ldb_module *module, struct ldb_request *req)
3680 struct ldb_context *ldb;
3681 static const char * const attrs[] = { "objectClass", "systemFlags",
3682 "isDeleted", NULL };
3683 struct ldb_request *search_req;
3684 struct samldb_ctx *ac;
3687 if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
3688 return ldb_next_request(module, req);
3691 ldb = ldb_module_get_ctx(module);
3693 ac = samldb_ctx_init(module, req);
3695 return ldb_oom(ldb);
3698 ret = ldb_build_search_req(&search_req, ldb, ac,
3699 req->op.rename.olddn,
3705 samldb_rename_search_base_callback,
3707 LDB_REQ_SET_LOCATION(search_req);
3708 if (ret != LDB_SUCCESS) {
3712 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
3714 if (ret != LDB_SUCCESS) {
3718 return ldb_next_request(ac->module, search_req);
3723 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
3725 struct ldb_context *ldb = ldb_module_get_ctx(module);
3726 struct dsdb_fsmo_extended_op *exop;
3729 exop = talloc_get_type(req->op.extended.data,
3730 struct dsdb_fsmo_extended_op);
3732 ldb_set_errstring(ldb,
3733 "samldb_extended_allocate_rid_pool: invalid extended data");
3734 return LDB_ERR_PROTOCOL_ERROR;
3737 ret = ridalloc_allocate_rid_pool_fsmo(module, exop, req);
3738 if (ret != LDB_SUCCESS) {
3742 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
3745 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
3747 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
3748 return samldb_extended_allocate_rid_pool(module, req);
3751 return ldb_next_request(module, req);
3755 static const struct ldb_module_ops ldb_samldb_module_ops = {
3758 .modify = samldb_modify,
3759 .del = samldb_delete,
3760 .rename = samldb_rename,
3761 .extended = samldb_extended
3765 int ldb_samldb_module_init(const char *version)
3767 LDB_MODULE_CHECK_VERSION(version);
3768 return ldb_register_module(&ldb_samldb_module_ops);