4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5 Copyright (C) Simo Sorce 2004-2008
6 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * Component: ldb samldb module
27 * Description: add embedded user/group creation functionality
33 #include "libcli/ldap/ldap_ndr.h"
34 #include "ldb_module.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
37 #include "libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
39 #include "../lib/util/util_ldb.h"
41 #include "param/param.h"
45 typedef int (*samldb_step_fn_t
)(struct samldb_ctx
*);
48 struct samldb_step
*next
;
53 struct ldb_module
*module
;
54 struct ldb_request
*req
;
56 /* used for add operations */
59 /* the resulting message */
60 struct ldb_message
*msg
;
62 /* used in "samldb_find_for_defaultObjectCategory" */
63 struct ldb_dn
*dn
, *res_dn
;
65 /* all the async steps necessary to complete the operation */
66 struct samldb_step
*steps
;
67 struct samldb_step
*curstep
;
69 /* If someone set an ares to forward controls and response back to the caller */
70 struct ldb_reply
*ares
;
73 static struct samldb_ctx
*samldb_ctx_init(struct ldb_module
*module
,
74 struct ldb_request
*req
)
76 struct ldb_context
*ldb
;
77 struct samldb_ctx
*ac
;
79 ldb
= ldb_module_get_ctx(module
);
81 ac
= talloc_zero(req
, struct samldb_ctx
);
93 static int samldb_add_step(struct samldb_ctx
*ac
, samldb_step_fn_t fn
)
95 struct samldb_step
*step
, *stepper
;
97 step
= talloc_zero(ac
, struct samldb_step
);
99 return ldb_oom(ldb_module_get_ctx(ac
->module
));
104 if (ac
->steps
== NULL
) {
108 if (ac
->curstep
== NULL
)
109 return ldb_operr(ldb_module_get_ctx(ac
->module
));
110 for (stepper
= ac
->curstep
; stepper
->next
!= NULL
;
111 stepper
= stepper
->next
);
112 stepper
->next
= step
;
118 static int samldb_first_step(struct samldb_ctx
*ac
)
120 if (ac
->steps
== NULL
) {
121 return ldb_operr(ldb_module_get_ctx(ac
->module
));
124 ac
->curstep
= ac
->steps
;
125 return ac
->curstep
->fn(ac
);
128 static int samldb_next_step(struct samldb_ctx
*ac
)
130 if (ac
->curstep
->next
) {
131 ac
->curstep
= ac
->curstep
->next
;
132 return ac
->curstep
->fn(ac
);
135 /* we exit the samldb module here */
136 /* If someone set an ares to forward controls and response back to the caller, use them */
138 return ldb_module_done(ac
->req
, ac
->ares
->controls
,
139 ac
->ares
->response
, LDB_SUCCESS
);
141 return ldb_module_done(ac
->req
, NULL
, NULL
, LDB_SUCCESS
);
146 /* sAMAccountName handling */
148 static int samldb_generate_sAMAccountName(struct ldb_context
*ldb
, struct ldb_message
*msg
)
152 /* Format: $000000-000000000000 */
154 name
= talloc_asprintf(msg
, "$%.6X-%.6X%.6X",
155 (unsigned int)generate_random(),
156 (unsigned int)generate_random(),
157 (unsigned int)generate_random());
161 return ldb_msg_add_steal_string(msg
, "sAMAccountName", name
);
164 static int samldb_check_sAMAccountName(struct samldb_ctx
*ac
)
166 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
170 if (ldb_msg_find_element(ac
->msg
, "sAMAccountName") == NULL
) {
171 ret
= samldb_generate_sAMAccountName(ldb
, ac
->msg
);
172 if (ret
!= LDB_SUCCESS
) {
177 name
= ldb_msg_find_attr_as_string(ac
->msg
, "sAMAccountName", NULL
);
179 return ldb_operr(ldb
);
182 ret
= samdb_search_count(ldb
, NULL
, "(sAMAccountName=%s)",
183 ldb_binary_encode_string(ac
, name
));
184 if ((ret
< 0) || (ret
> 1)) {
185 return ldb_operr(ldb
);
188 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
191 return samldb_next_step(ac
);
194 /* sAMAccountType handling */
196 static int samldb_check_sAMAccountType(struct samldb_ctx
*ac
)
198 struct ldb_context
*ldb
;
199 unsigned int account_type
;
200 unsigned int group_type
;
204 ldb
= ldb_module_get_ctx(ac
->module
);
206 /* make sure sAMAccountType is not specified */
207 if (ldb_msg_find_element(ac
->msg
, "sAMAccountType") != NULL
) {
208 ldb_asprintf_errstring(ldb
,
209 "sAMAccountType must not be specified!");
210 return LDB_ERR_UNWILLING_TO_PERFORM
;
213 if (strcmp("user", ac
->type
) == 0) {
214 uac
= samdb_result_uint(ac
->msg
, "userAccountControl", 0);
216 ldb_asprintf_errstring(ldb
,
217 "userAccountControl invalid!");
218 return LDB_ERR_UNWILLING_TO_PERFORM
;
220 account_type
= ds_uf2atype(uac
);
221 ret
= samdb_msg_add_uint(ldb
,
225 if (ret
!= LDB_SUCCESS
) {
229 } else if (strcmp("group", ac
->type
) == 0) {
230 group_type
= samdb_result_uint(ac
->msg
, "groupType", 0);
231 if (group_type
== 0) {
232 ldb_asprintf_errstring(ldb
,
233 "groupType invalid!\n");
234 return LDB_ERR_UNWILLING_TO_PERFORM
;
236 account_type
= ds_gtype2atype(group_type
);
237 ret
= samdb_msg_add_uint(ldb
,
241 if (ret
!= LDB_SUCCESS
) {
247 return samldb_next_step(ac
);
250 /* primaryGroupID handling */
252 static int samldb_check_primaryGroupID(struct samldb_ctx
*ac
)
254 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
255 struct ldb_dn
*prim_group_dn
;
260 rid
= samdb_result_uint(ac
->msg
, "primaryGroupID", (uint32_t) -1);
261 if (rid
== (uint32_t) -1) {
262 rid
= DOMAIN_RID_USERS
;
263 ret
= samdb_msg_add_uint(ldb
, ac
->msg
, ac
->msg
,
264 "primaryGroupID", rid
);
265 if (ret
!= LDB_SUCCESS
) {
270 sid
= dom_sid_add_rid(ac
, samdb_domain_sid(ldb
), rid
);
272 return ldb_operr(ldb
);
275 prim_group_dn
= samdb_search_dn(ldb
, ac
, NULL
, "(objectSID=%s)",
276 dom_sid_string(ac
, sid
));
277 if (prim_group_dn
== NULL
) {
278 ldb_asprintf_errstring(ldb
,
279 "Failed to find primary group with RID %u!",
281 return LDB_ERR_UNWILLING_TO_PERFORM
;
284 return samldb_next_step(ac
);
288 static bool samldb_msg_add_sid(struct ldb_message
*msg
,
290 const struct dom_sid
*sid
)
293 enum ndr_err_code ndr_err
;
295 ndr_err
= ndr_push_struct_blob(&v
, msg
, sid
,
296 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
297 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
300 return (ldb_msg_add_value(msg
, name
, &v
, NULL
) == 0);
304 /* allocate a SID using our RID Set */
305 static int samldb_allocate_sid(struct samldb_ctx
*ac
)
309 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
312 ret
= ridalloc_allocate_rid(ac
->module
, &rid
);
313 if (ret
!= LDB_SUCCESS
) {
317 sid
= dom_sid_add_rid(ac
, samdb_domain_sid(ldb
), rid
);
319 return ldb_module_oom(ac
->module
);
322 if ( ! samldb_msg_add_sid(ac
->msg
, "objectSid", sid
)) {
323 return ldb_operr(ldb
);
326 return samldb_next_step(ac
);
330 see if a krbtgt_number is available
332 static bool samldb_krbtgtnumber_available(struct samldb_ctx
*ac
, unsigned krbtgt_number
)
334 TALLOC_CTX
*tmp_ctx
= talloc_new(ac
);
335 struct ldb_result
*res
;
336 const char *attrs
[] = { NULL
};
339 ret
= dsdb_module_search(ac
->module
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
340 attrs
, DSDB_FLAG_NEXT_MODULE
,
341 "msDC-SecondaryKrbTgtNumber=%u", krbtgt_number
);
342 if (ret
== LDB_SUCCESS
&& res
->count
== 0) {
343 talloc_free(tmp_ctx
);
346 talloc_free(tmp_ctx
);
350 /* special handling for add in RODC join */
351 static int samldb_rodc_add(struct samldb_ctx
*ac
)
353 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
354 unsigned krbtgt_number
, i_start
, i
;
357 /* find a unused msDC-SecondaryKrbTgtNumber */
358 i_start
= generate_random() & 0xFFFF;
363 for (i
=i_start
; i
<=0xFFFF; i
++) {
364 if (samldb_krbtgtnumber_available(ac
, i
)) {
369 for (i
=1; i
<i_start
; i
++) {
370 if (samldb_krbtgtnumber_available(ac
, i
)) {
376 ldb_asprintf_errstring(ldb_module_get_ctx(ac
->module
),
377 "%08X: Unable to find available msDS-SecondaryKrbTgtNumber",
378 W_ERROR_V(WERR_NO_SYSTEM_RESOURCES
));
379 return LDB_ERR_OTHER
;
382 ret
= ldb_msg_add_empty(ac
->msg
, "msDS-SecondaryKrbTgtNumber", LDB_FLAG_INTERNAL_DISABLE_VALIDATION
, NULL
);
383 if (ret
!= LDB_SUCCESS
) {
384 return ldb_operr(ldb
);
387 ret
= ldb_msg_add_fmt(ac
->msg
, "msDS-SecondaryKrbTgtNumber", "%u", krbtgt_number
);
388 if (ret
!= LDB_SUCCESS
) {
389 return ldb_operr(ldb
);
392 ret
= ldb_msg_add_fmt(ac
->msg
, "sAMAccountName", "krbtgt_%u", krbtgt_number
);
393 if (ret
!= LDB_SUCCESS
) {
394 return ldb_operr(ldb
);
397 return samldb_next_step(ac
);
400 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx
*ac
)
402 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
403 struct ldb_result
*res
;
404 const char *no_attrs
[] = { NULL
};
409 ret
= dsdb_module_search(ac
->module
, ac
, &res
,
410 ac
->dn
, LDB_SCOPE_BASE
, no_attrs
,
411 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
| DSDB_FLAG_NEXT_MODULE
,
412 "(objectClass=classSchema)");
413 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
414 /* Don't be pricky when the DN doesn't exist if we have the */
415 /* RELAX control specified */
416 if (ldb_request_get_control(ac
->req
,
417 LDB_CONTROL_RELAX_OID
) == NULL
) {
418 ldb_set_errstring(ldb
,
419 "samldb_find_defaultObjectCategory: "
420 "Invalid DN for 'defaultObjectCategory'!");
421 return LDB_ERR_CONSTRAINT_VIOLATION
;
424 if ((ret
!= LDB_ERR_NO_SUCH_OBJECT
) && (ret
!= LDB_SUCCESS
)) {
430 return samldb_next_step(ac
);
434 * msDS-IntId attributeSchema attribute handling
435 * during LDB_ADD request processing
437 static int samldb_add_handle_msDS_IntId(struct samldb_ctx
*ac
)
442 uint32_t system_flags
;
443 struct ldb_context
*ldb
;
444 struct ldb_result
*ldb_res
;
445 struct ldb_dn
*schema_dn
;
447 ldb
= ldb_module_get_ctx(ac
->module
);
448 schema_dn
= ldb_get_schema_basedn(ldb
);
450 /* replicated update should always go through */
451 if (ldb_request_get_control(ac
->req
, DSDB_CONTROL_REPLICATED_UPDATE_OID
)) {
455 /* msDS-IntId is handled by system and should never be
456 * passed by clients */
457 if (ldb_msg_find_element(ac
->msg
, "msDS-IntId")) {
458 return LDB_ERR_UNWILLING_TO_PERFORM
;
461 /* do not generate msDS-IntId if Relax control is passed */
462 if (ldb_request_get_control(ac
->req
, LDB_CONTROL_RELAX_OID
)) {
466 /* check Functional Level */
467 if (dsdb_functional_level(ldb
) < DS_DOMAIN_FUNCTION_2003
) {
471 /* check systemFlags for SCHEMA_BASE_OBJECT flag */
472 system_flags
= ldb_msg_find_attr_as_uint(ac
->msg
, "systemFlags", 0);
473 if (system_flags
& SYSTEM_FLAG_SCHEMA_BASE_OBJECT
) {
477 /* Generate new value for msDs-IntId
478 * Value should be in 0x80000000..0xBFFFFFFF range */
479 msds_intid
= generate_random() % 0X3FFFFFFF;
480 msds_intid
+= 0x80000000;
482 /* probe id values until unique one is found */
485 if (msds_intid
> 0xBFFFFFFF) {
486 msds_intid
= 0x80000001;
489 ret
= dsdb_module_search(ac
->module
, ac
,
491 schema_dn
, LDB_SCOPE_ONELEVEL
, NULL
,
492 DSDB_FLAG_NEXT_MODULE
,
493 "(msDS-IntId=%d)", msds_intid
);
494 if (ret
!= LDB_SUCCESS
) {
495 ldb_debug_set(ldb
, LDB_DEBUG_ERROR
,
496 __location__
": Searching for msDS-IntId=%d failed - %s\n",
499 return ldb_operr(ldb
);
501 id_exists
= (ldb_res
->count
> 0);
503 talloc_free(ldb_res
);
506 return ldb_msg_add_fmt(ac
->msg
, "msDS-IntId", "%d", msds_intid
);
511 * samldb_add_entry (async)
514 static int samldb_add_entry_callback(struct ldb_request
*req
,
515 struct ldb_reply
*ares
)
517 struct ldb_context
*ldb
;
518 struct samldb_ctx
*ac
;
521 ac
= talloc_get_type(req
->context
, struct samldb_ctx
);
522 ldb
= ldb_module_get_ctx(ac
->module
);
525 return ldb_module_done(ac
->req
, NULL
, NULL
,
526 LDB_ERR_OPERATIONS_ERROR
);
529 if (ares
->type
== LDB_REPLY_REFERRAL
) {
530 return ldb_module_send_referral(ac
->req
, ares
->referral
);
533 if (ares
->error
!= LDB_SUCCESS
) {
534 return ldb_module_done(ac
->req
, ares
->controls
,
535 ares
->response
, ares
->error
);
537 if (ares
->type
!= LDB_REPLY_DONE
) {
538 ldb_set_errstring(ldb
,
539 "Invalid reply type!\n");
540 return ldb_module_done(ac
->req
, NULL
, NULL
,
541 LDB_ERR_OPERATIONS_ERROR
);
544 /* The caller may wish to get controls back from the add */
545 ac
->ares
= talloc_steal(ac
, ares
);
547 ret
= samldb_next_step(ac
);
548 if (ret
!= LDB_SUCCESS
) {
549 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
554 static int samldb_add_entry(struct samldb_ctx
*ac
)
556 struct ldb_context
*ldb
;
557 struct ldb_request
*req
;
560 ldb
= ldb_module_get_ctx(ac
->module
);
562 ret
= ldb_build_add_req(&req
, ldb
, ac
,
565 ac
, samldb_add_entry_callback
,
567 if (ret
!= LDB_SUCCESS
) {
571 return ldb_next_request(ac
->module
, req
);
575 * return true if msg carries an attributeSchema that is intended to be RODC
576 * filtered but is also a system-critical attribute.
578 static bool check_rodc_critical_attribute(struct ldb_message
*msg
)
580 uint32_t schemaFlagsEx
, searchFlags
, rodc_filtered_flags
;
582 schemaFlagsEx
= ldb_msg_find_attr_as_uint(msg
, "schemaFlagsEx", 0);
583 searchFlags
= ldb_msg_find_attr_as_uint(msg
, "searchFlags", 0);
584 rodc_filtered_flags
= (SEARCH_FLAG_RODC_ATTRIBUTE
| SEARCH_FLAG_CONFIDENTIAL
);
586 if ((schemaFlagsEx
& SCHEMA_FLAG_ATTR_IS_CRITICAL
) &&
587 ((searchFlags
& rodc_filtered_flags
) == rodc_filtered_flags
)) {
595 static int samldb_fill_object(struct samldb_ctx
*ac
, const char *type
)
597 struct ldb_context
*ldb
;
598 struct loadparm_context
*lp_ctx
;
599 enum sid_generator sid_generator
;
601 struct ldb_control
*rodc_control
;
604 ldb
= ldb_module_get_ctx(ac
->module
);
606 /* Add informations for the different account types */
608 if (strcmp(ac
->type
, "user") == 0) {
609 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
610 "userAccountControl", "546");
611 if (ret
!= LDB_SUCCESS
) return ret
;
612 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
614 if (ret
!= LDB_SUCCESS
) return ret
;
615 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
617 if (ret
!= LDB_SUCCESS
) return ret
;
618 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
620 if (ret
!= LDB_SUCCESS
) return ret
;
621 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
622 "badPasswordTime", "0");
623 if (ret
!= LDB_SUCCESS
) return ret
;
624 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
626 if (ret
!= LDB_SUCCESS
) return ret
;
627 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
629 if (ret
!= LDB_SUCCESS
) return ret
;
630 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
632 if (ret
!= LDB_SUCCESS
) return ret
;
633 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
634 "accountExpires", "9223372036854775807");
635 if (ret
!= LDB_SUCCESS
) return ret
;
636 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
638 if (ret
!= LDB_SUCCESS
) return ret
;
639 } else if (strcmp(ac
->type
, "group") == 0) {
640 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
641 "groupType", "-2147483646");
642 if (ret
!= LDB_SUCCESS
) return ret
;
643 } else if (strcmp(ac
->type
, "classSchema") == 0) {
644 const struct ldb_val
*rdn_value
, *def_obj_cat_val
;
646 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
648 if (ret
!= LDB_SUCCESS
) return ret
;
650 /* do not allow to mark an attributeSchema as RODC filtered if it
651 * is system-critical */
652 if (check_rodc_critical_attribute(ac
->msg
)) {
653 ldb_asprintf_errstring(ldb
, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
654 ldb_dn_get_linearized(ac
->msg
->dn
));
655 return LDB_ERR_UNWILLING_TO_PERFORM
;
659 rdn_value
= ldb_dn_get_rdn_val(ac
->msg
->dn
);
660 if (!ldb_msg_find_element(ac
->msg
, "lDAPDisplayName")) {
661 /* the RDN has prefix "CN" */
662 ret
= ldb_msg_add_string(ac
->msg
, "lDAPDisplayName",
663 samdb_cn_to_lDAPDisplayName(ac
,
664 (const char *) rdn_value
->data
));
665 if (ret
!= LDB_SUCCESS
) {
671 if (!ldb_msg_find_element(ac
->msg
, "schemaIDGUID")) {
674 guid
= GUID_random();
675 ret
= dsdb_msg_add_guid(ac
->msg
, &guid
, "schemaIDGUID");
676 if (ret
!= LDB_SUCCESS
) {
682 def_obj_cat_val
= ldb_msg_find_ldb_val(ac
->msg
,
683 "defaultObjectCategory");
684 if (def_obj_cat_val
!= NULL
) {
685 /* "defaultObjectCategory" has been set by the caller.
686 * Do some checks for consistency.
687 * NOTE: The real constraint check (that
688 * 'defaultObjectCategory' is the DN of the new
689 * objectclass or any parent of it) is still incomplete.
690 * For now we say that 'defaultObjectCategory' is valid
691 * if it exists and it is of objectclass "classSchema".
693 ac
->dn
= ldb_dn_from_ldb_val(ac
, ldb
, def_obj_cat_val
);
694 if (ac
->dn
== NULL
) {
695 ldb_set_errstring(ldb
,
696 "Invalid DN for 'defaultObjectCategory'!");
697 return LDB_ERR_CONSTRAINT_VIOLATION
;
700 /* "defaultObjectCategory" has not been set by the
701 * caller. Use the entry DN for it. */
702 ac
->dn
= ac
->msg
->dn
;
704 ret
= samdb_msg_add_string(ldb
, ac
, ac
->msg
,
705 "defaultObjectCategory",
706 ldb_dn_get_linearized(ac
->dn
));
707 if (ret
!= LDB_SUCCESS
) {
713 ret
= samldb_add_step(ac
, samldb_add_entry
);
714 if (ret
!= LDB_SUCCESS
) return ret
;
716 /* Now perform the checks for the 'defaultObjectCategory'. The
717 * lookup DN was already saved in "ac->dn" */
718 ret
= samldb_add_step(ac
, samldb_find_for_defaultObjectCategory
);
719 if (ret
!= LDB_SUCCESS
) return ret
;
721 return samldb_first_step(ac
);
722 } else if (strcmp(ac
->type
, "attributeSchema") == 0) {
723 const struct ldb_val
*rdn_value
;
724 rdn_value
= ldb_dn_get_rdn_val(ac
->msg
->dn
);
725 if (!ldb_msg_find_element(ac
->msg
, "lDAPDisplayName")) {
726 /* the RDN has prefix "CN" */
727 ret
= ldb_msg_add_string(ac
->msg
, "lDAPDisplayName",
728 samdb_cn_to_lDAPDisplayName(ac
,
729 (const char *) rdn_value
->data
));
730 if (ret
!= LDB_SUCCESS
) {
736 /* do not allow to mark an attributeSchema as RODC filtered if it
737 * is system-critical */
738 if (check_rodc_critical_attribute(ac
->msg
)) {
739 ldb_asprintf_errstring(ldb
, "Refusing schema add of %s - cannot combine critical attribute with RODC filtering",
740 ldb_dn_get_linearized(ac
->msg
->dn
));
741 return LDB_ERR_UNWILLING_TO_PERFORM
;
744 ret
= samdb_find_or_add_attribute(ldb
, ac
->msg
,
745 "isSingleValued", "FALSE");
746 if (ret
!= LDB_SUCCESS
) return ret
;
748 if (!ldb_msg_find_element(ac
->msg
, "schemaIDGUID")) {
751 guid
= GUID_random();
752 ret
= dsdb_msg_add_guid(ac
->msg
, &guid
, "schemaIDGUID");
753 if (ret
!= LDB_SUCCESS
) {
759 /* handle msDS-IntID attribute */
760 ret
= samldb_add_handle_msDS_IntId(ac
);
761 if (ret
!= LDB_SUCCESS
) return ret
;
763 ret
= samldb_add_step(ac
, samldb_add_entry
);
764 if (ret
!= LDB_SUCCESS
) return ret
;
766 return samldb_first_step(ac
);
768 ldb_asprintf_errstring(ldb
,
769 "Invalid entry type!");
770 return LDB_ERR_OPERATIONS_ERROR
;
773 rodc_control
= ldb_request_get_control(ac
->req
, LDB_CONTROL_RODC_DCPROMO_OID
);
775 /* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
776 rodc_control
->critical
= false;
777 ret
= samldb_add_step(ac
, samldb_rodc_add
);
778 if (ret
!= LDB_SUCCESS
) return ret
;
781 /* check if we have a valid sAMAccountName */
782 ret
= samldb_add_step(ac
, samldb_check_sAMAccountName
);
783 if (ret
!= LDB_SUCCESS
) return ret
;
785 /* check account_type/group_type */
786 ret
= samldb_add_step(ac
, samldb_check_sAMAccountType
);
787 if (ret
!= LDB_SUCCESS
) return ret
;
789 /* check if we have a valid primary group ID */
790 if (strcmp(ac
->type
, "user") == 0) {
791 ret
= samldb_add_step(ac
, samldb_check_primaryGroupID
);
792 if (ret
!= LDB_SUCCESS
) return ret
;
795 lp_ctx
= talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
796 struct loadparm_context
);
798 /* don't allow objectSID to be specified without the RELAX control */
799 sid
= samdb_result_dom_sid(ac
, ac
->msg
, "objectSid");
800 if (sid
&& !ldb_request_get_control(ac
->req
, LDB_CONTROL_RELAX_OID
) &&
801 !dsdb_module_am_system(ac
->module
)) {
802 ldb_asprintf_errstring(ldb
, "No SID may be specified in user/group creation for %s",
803 ldb_dn_get_linearized(ac
->msg
->dn
));
804 return LDB_ERR_UNWILLING_TO_PERFORM
;
808 sid_generator
= lpcfg_sid_generator(lp_ctx
);
809 if (sid_generator
== SID_GENERATOR_INTERNAL
) {
810 ret
= samldb_add_step(ac
, samldb_allocate_sid
);
811 if (ret
!= LDB_SUCCESS
) return ret
;
815 /* finally proceed with adding the entry */
816 ret
= samldb_add_step(ac
, samldb_add_entry
);
817 if (ret
!= LDB_SUCCESS
) return ret
;
819 return samldb_first_step(ac
);
822 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx
*ac
)
824 struct ldb_context
*ldb
;
828 ldb
= ldb_module_get_ctx(ac
->module
);
830 sid
= samdb_result_dom_sid(ac
->msg
, ac
->msg
, "objectSid");
832 sid
= dom_sid_parse_talloc(ac
->msg
,
833 (const char *)ldb_dn_get_rdn_val(ac
->msg
->dn
)->data
);
835 ldb_set_errstring(ldb
,
836 "No valid SID found in "
837 "ForeignSecurityPrincipal CN!");
838 return LDB_ERR_CONSTRAINT_VIOLATION
;
840 if (! samldb_msg_add_sid(ac
->msg
, "objectSid", sid
)) {
841 return ldb_operr(ldb
);
845 /* finally proceed with adding the entry */
846 ret
= samldb_add_step(ac
, samldb_add_entry
);
847 if (ret
!= LDB_SUCCESS
) return ret
;
849 return samldb_first_step(ac
);
852 static int samldb_schema_info_update(struct samldb_ctx
*ac
)
855 struct ldb_context
*ldb
;
856 struct dsdb_schema
*schema
;
858 /* replicated update should always go through */
859 if (ldb_request_get_control(ac
->req
, DSDB_CONTROL_REPLICATED_UPDATE_OID
)) {
863 /* do not update schemaInfo during provisioning */
864 if (ldb_request_get_control(ac
->req
, LDB_CONTROL_RELAX_OID
)) {
868 ldb
= ldb_module_get_ctx(ac
->module
);
869 schema
= dsdb_get_schema(ldb
, NULL
);
871 ldb_debug_set(ldb
, LDB_DEBUG_FATAL
,
872 "samldb_schema_info_update: no dsdb_schema loaded");
873 DEBUG(0,(__location__
": %s\n", ldb_errstring(ldb
)));
874 return ldb_operr(ldb
);
877 werr
= dsdb_module_schema_info_update(ac
->module
, schema
, DSDB_FLAG_NEXT_MODULE
);
878 if (!W_ERROR_IS_OK(werr
)) {
879 ldb_debug_set(ldb
, LDB_DEBUG_FATAL
,
880 "samldb_schema_info_update: "
881 "dsdb_module_schema_info_update failed with %s",
883 DEBUG(0,(__location__
": %s\n", ldb_errstring(ldb
)));
884 return ldb_operr(ldb
);
891 static int samldb_prim_group_change(struct samldb_ctx
*ac
)
893 struct ldb_context
*ldb
;
894 const char * attrs
[] = { "primaryGroupID", "memberOf", NULL
};
895 struct ldb_result
*res
;
896 struct ldb_message_element
*el
;
897 struct ldb_message
*msg
;
900 struct ldb_dn
*prev_prim_group_dn
, *new_prim_group_dn
;
903 ldb
= ldb_module_get_ctx(ac
->module
);
905 /* Fetch informations from the existing object */
907 ret
= ldb_search(ldb
, ac
, &res
, ac
->msg
->dn
, LDB_SCOPE_BASE
, attrs
,
909 if (ret
!= LDB_SUCCESS
) {
913 /* Finds out the DN of the old primary group */
915 rid
= samdb_result_uint(res
->msgs
[0], "primaryGroupID", (uint32_t) -1);
916 if (rid
== (uint32_t) -1) {
917 /* User objects do always have a mandatory "primaryGroupID"
918 * attribute. If this doesn't exist then the object is of the
919 * wrong type. This is the exact Windows error code */
920 return LDB_ERR_OBJECT_CLASS_VIOLATION
;
923 sid
= dom_sid_add_rid(ac
, samdb_domain_sid(ldb
), rid
);
925 return ldb_operr(ldb
);
928 prev_prim_group_dn
= samdb_search_dn(ldb
, ac
, NULL
, "(objectSID=%s)",
929 dom_sid_string(ac
, sid
));
930 if (prev_prim_group_dn
== NULL
) {
931 return ldb_operr(ldb
);
934 /* Finds out the DN of the new primary group */
936 rid
= samdb_result_uint(ac
->msg
, "primaryGroupID", (uint32_t) -1);
937 if (rid
== (uint32_t) -1) {
938 /* we aren't affected of any primary group change */
942 sid
= dom_sid_add_rid(ac
, samdb_domain_sid(ldb
), rid
);
944 return ldb_operr(ldb
);
947 new_prim_group_dn
= samdb_search_dn(ldb
, ac
, NULL
, "(objectSID=%s)",
948 dom_sid_string(ac
, sid
));
949 if (new_prim_group_dn
== NULL
) {
950 /* Here we know if the specified new primary group candidate is
952 return LDB_ERR_UNWILLING_TO_PERFORM
;
955 /* Only update the "member" attributes when we really do have a change */
956 if (ldb_dn_compare(new_prim_group_dn
, prev_prim_group_dn
) != 0) {
957 /* We need to be already a normal member of the new primary
958 * group in order to be successful. */
959 el
= samdb_find_attribute(ldb
, res
->msgs
[0], "memberOf",
960 ldb_dn_get_linearized(new_prim_group_dn
));
962 return LDB_ERR_UNWILLING_TO_PERFORM
;
965 /* Remove the "member" attribute on the new primary group */
966 msg
= talloc_zero(ac
, struct ldb_message
);
967 msg
->dn
= new_prim_group_dn
;
969 ret
= samdb_msg_add_delval(ldb
, ac
, msg
, "member",
970 ldb_dn_get_linearized(ac
->msg
->dn
));
971 if (ret
!= LDB_SUCCESS
) {
975 ret
= dsdb_module_modify(ac
->module
, msg
, DSDB_FLAG_NEXT_MODULE
);
976 if (ret
!= LDB_SUCCESS
) {
980 /* Add a "member" attribute for the previous primary group */
981 msg
= talloc_zero(ac
, struct ldb_message
);
982 msg
->dn
= prev_prim_group_dn
;
984 ret
= samdb_msg_add_addval(ldb
, ac
, msg
, "member",
985 ldb_dn_get_linearized(ac
->msg
->dn
));
986 if (ret
!= LDB_SUCCESS
) {
990 ret
= dsdb_module_modify(ac
->module
, msg
, DSDB_FLAG_NEXT_MODULE
);
991 if (ret
!= LDB_SUCCESS
) {
1000 static int samldb_member_check(struct samldb_ctx
*ac
)
1002 struct ldb_context
*ldb
;
1003 struct ldb_message_element
*el
;
1004 struct ldb_dn
*member_dn
, *group_dn
;
1005 uint32_t prim_group_rid
;
1006 struct dom_sid
*sid
;
1009 ldb
= ldb_module_get_ctx(ac
->module
);
1011 el
= ldb_msg_find_element(ac
->msg
, "member");
1013 /* we aren't affected */
1017 for (i
= 0; i
< el
->num_values
; i
++) {
1018 /* Denies to add "member"s to groups which are primary ones
1020 member_dn
= ldb_dn_from_ldb_val(ac
, ldb
, &el
->values
[i
]);
1021 if (!ldb_dn_validate(member_dn
)) {
1022 return ldb_operr(ldb
);
1025 prim_group_rid
= samdb_search_uint(ldb
, ac
, (uint32_t) -1,
1026 member_dn
, "primaryGroupID",
1028 if (prim_group_rid
== (uint32_t) -1) {
1029 /* the member hasn't to be a user account -> therefore
1030 * no check needed in this case. */
1034 sid
= dom_sid_add_rid(ac
, samdb_domain_sid(ldb
),
1037 return ldb_operr(ldb
);
1040 group_dn
= samdb_search_dn(ldb
, ac
, NULL
, "(objectSID=%s)",
1041 dom_sid_string(ac
, sid
));
1042 if (group_dn
== NULL
) {
1043 return ldb_operr(ldb
);
1046 if (ldb_dn_compare(group_dn
, ac
->msg
->dn
) == 0) {
1047 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1056 static int samldb_add(struct ldb_module
*module
, struct ldb_request
*req
)
1058 struct ldb_context
*ldb
;
1059 struct samldb_ctx
*ac
;
1062 ldb
= ldb_module_get_ctx(module
);
1063 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "samldb_add\n");
1065 /* do not manipulate our control entries */
1066 if (ldb_dn_is_special(req
->op
.add
.message
->dn
)) {
1067 return ldb_next_request(module
, req
);
1070 ac
= samldb_ctx_init(module
, req
);
1072 return ldb_operr(ldb
);
1075 /* build the new msg */
1076 ac
->msg
= ldb_msg_copy(ac
, ac
->req
->op
.add
.message
);
1079 ldb_debug(ldb
, LDB_DEBUG_FATAL
,
1080 "samldb_add: ldb_msg_copy failed!\n");
1081 return ldb_operr(ldb
);
1084 if (samdb_find_attribute(ldb
, ac
->msg
,
1085 "objectclass", "user") != NULL
) {
1086 return samldb_fill_object(ac
, "user");
1089 if (samdb_find_attribute(ldb
, ac
->msg
,
1090 "objectclass", "group") != NULL
) {
1091 return samldb_fill_object(ac
, "group");
1094 /* perhaps a foreignSecurityPrincipal? */
1095 if (samdb_find_attribute(ldb
, ac
->msg
,
1097 "foreignSecurityPrincipal") != NULL
) {
1098 return samldb_fill_foreignSecurityPrincipal_object(ac
);
1101 if (samdb_find_attribute(ldb
, ac
->msg
,
1102 "objectclass", "classSchema") != NULL
) {
1103 ret
= samldb_schema_info_update(ac
);
1104 if (ret
!= LDB_SUCCESS
) {
1109 return samldb_fill_object(ac
, "classSchema");
1112 if (samdb_find_attribute(ldb
, ac
->msg
,
1113 "objectclass", "attributeSchema") != NULL
) {
1114 ret
= samldb_schema_info_update(ac
);
1115 if (ret
!= LDB_SUCCESS
) {
1120 return samldb_fill_object(ac
, "attributeSchema");
1125 /* nothing matched, go on */
1126 return ldb_next_request(module
, req
);
1130 static int samldb_modify(struct ldb_module
*module
, struct ldb_request
*req
)
1132 struct ldb_context
*ldb
;
1133 struct samldb_ctx
*ac
;
1134 struct ldb_message
*msg
;
1135 struct ldb_message_element
*el
, *el2
;
1137 uint32_t account_type
;
1139 if (ldb_dn_is_special(req
->op
.mod
.message
->dn
)) {
1140 /* do not manipulate our control entries */
1141 return ldb_next_request(module
, req
);
1144 ldb
= ldb_module_get_ctx(module
);
1146 if (ldb_msg_find_element(req
->op
.mod
.message
, "sAMAccountType") != NULL
) {
1147 ldb_asprintf_errstring(ldb
,
1148 "sAMAccountType must not be specified!");
1149 return LDB_ERR_UNWILLING_TO_PERFORM
;
1152 /* msDS-IntId is not allowed to be modified
1153 * except when modification comes from replication */
1154 if (ldb_msg_find_element(req
->op
.mod
.message
, "msDS-IntId")) {
1155 if (!ldb_request_get_control(req
, DSDB_CONTROL_REPLICATED_UPDATE_OID
)) {
1156 return LDB_ERR_CONSTRAINT_VIOLATION
;
1160 ac
= samldb_ctx_init(module
, req
);
1162 return ldb_operr(ldb
);
1165 /* TODO: do not modify original request, create a new one */
1167 el
= ldb_msg_find_element(req
->op
.mod
.message
, "groupType");
1168 if (el
&& (LDB_FLAG_MOD_TYPE(el
->flags
) == LDB_FLAG_MOD_REPLACE
) && el
->num_values
== 1) {
1169 uint32_t group_type
;
1171 req
->op
.mod
.message
= msg
= ldb_msg_copy_shallow(req
,
1172 req
->op
.mod
.message
);
1174 group_type
= strtoul((const char *)el
->values
[0].data
, NULL
, 0);
1175 account_type
= ds_gtype2atype(group_type
);
1176 ret
= samdb_msg_add_uint(ldb
, msg
, msg
,
1179 if (ret
!= LDB_SUCCESS
) {
1182 el2
= ldb_msg_find_element(msg
, "sAMAccountType");
1183 el2
->flags
= LDB_FLAG_MOD_REPLACE
;
1185 if (el
&& (LDB_FLAG_MOD_TYPE(el
->flags
) == LDB_FLAG_MOD_DELETE
)) {
1186 return LDB_ERR_UNWILLING_TO_PERFORM
;
1189 el
= ldb_msg_find_element(req
->op
.mod
.message
, "primaryGroupID");
1190 if (el
&& (LDB_FLAG_MOD_TYPE(el
->flags
) == LDB_FLAG_MOD_REPLACE
) && el
->num_values
== 1) {
1191 req
->op
.mod
.message
= ac
->msg
= ldb_msg_copy_shallow(req
,
1192 req
->op
.mod
.message
);
1194 ret
= samldb_prim_group_change(ac
);
1195 if (ret
!= LDB_SUCCESS
) {
1199 if (el
&& (LDB_FLAG_MOD_TYPE(el
->flags
) == LDB_FLAG_MOD_DELETE
)) {
1200 return LDB_ERR_UNWILLING_TO_PERFORM
;
1203 el
= ldb_msg_find_element(req
->op
.mod
.message
, "userAccountControl");
1204 if (el
&& (LDB_FLAG_MOD_TYPE(el
->flags
) == LDB_FLAG_MOD_REPLACE
) && el
->num_values
== 1) {
1205 uint32_t user_account_control
;
1207 req
->op
.mod
.message
= msg
= ldb_msg_copy_shallow(req
,
1208 req
->op
.mod
.message
);
1210 user_account_control
= strtoul((const char *)el
->values
[0].data
,
1212 account_type
= ds_uf2atype(user_account_control
);
1213 ret
= samdb_msg_add_uint(ldb
, msg
, msg
,
1216 if (ret
!= LDB_SUCCESS
) {
1219 el2
= ldb_msg_find_element(msg
, "sAMAccountType");
1220 el2
->flags
= LDB_FLAG_MOD_REPLACE
;
1222 if (user_account_control
& (UF_SERVER_TRUST_ACCOUNT
| UF_PARTIAL_SECRETS_ACCOUNT
)) {
1223 ret
= samdb_msg_add_string(ldb
, msg
, msg
,
1224 "isCriticalSystemObject", "TRUE");
1225 if (ret
!= LDB_SUCCESS
) {
1228 el2
= ldb_msg_find_element(msg
, "isCriticalSystemObject");
1229 el2
->flags
= LDB_FLAG_MOD_REPLACE
;
1231 /* DCs have primaryGroupID of DOMAIN_RID_DCS */
1232 if (!ldb_msg_find_element(msg
, "primaryGroupID")) {
1234 if (user_account_control
& UF_SERVER_TRUST_ACCOUNT
) {
1235 rid
= DOMAIN_RID_DCS
;
1238 rid
= DOMAIN_RID_READONLY_DCS
;
1240 ret
= samdb_msg_add_uint(ldb
, msg
, msg
,
1241 "primaryGroupID", rid
);
1242 if (ret
!= LDB_SUCCESS
) {
1245 el2
= ldb_msg_find_element(msg
, "primaryGroupID");
1246 el2
->flags
= LDB_FLAG_MOD_REPLACE
;
1250 if (el
&& (LDB_FLAG_MOD_TYPE(el
->flags
) == LDB_FLAG_MOD_DELETE
)) {
1251 return LDB_ERR_UNWILLING_TO_PERFORM
;
1254 el
= ldb_msg_find_element(req
->op
.mod
.message
, "member");
1255 if (el
&& el
->flags
& (LDB_FLAG_MOD_ADD
|LDB_FLAG_MOD_REPLACE
) && el
->num_values
== 1) {
1256 req
->op
.mod
.message
= ac
->msg
= ldb_msg_copy_shallow(req
,
1257 req
->op
.mod
.message
);
1259 ret
= samldb_member_check(ac
);
1260 if (ret
!= LDB_SUCCESS
) {
1265 return ldb_next_request(module
, req
);
1270 static int samldb_prim_group_users_check(struct samldb_ctx
*ac
)
1272 struct ldb_context
*ldb
;
1273 struct dom_sid
*sid
;
1278 ldb
= ldb_module_get_ctx(ac
->module
);
1280 /* Finds out the SID/RID of the SAM object */
1281 sid
= samdb_search_dom_sid(ldb
, ac
, ac
->req
->op
.del
.dn
, "objectSID",
1284 /* No SID - it might not be a SAM object - therefore ok */
1287 status
= dom_sid_split_rid(ac
, sid
, NULL
, &rid
);
1288 if (!NT_STATUS_IS_OK(status
)) {
1289 return ldb_operr(ldb
);
1292 /* Special object (security principal?) */
1296 /* Deny delete requests from groups which are primary ones */
1297 count
= samdb_search_count(ldb
, NULL
,
1298 "(&(primaryGroupID=%u)(objectClass=user))",
1301 return ldb_operr(ldb
);
1304 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1310 static int samldb_delete(struct ldb_module
*module
, struct ldb_request
*req
)
1312 struct samldb_ctx
*ac
;
1315 if (ldb_dn_is_special(req
->op
.del
.dn
)) {
1316 /* do not manipulate our control entries */
1317 return ldb_next_request(module
, req
);
1320 ac
= samldb_ctx_init(module
, req
);
1322 return ldb_operr(ldb_module_get_ctx(module
));
1324 ret
= samldb_prim_group_users_check(ac
);
1325 if (ret
!= LDB_SUCCESS
) {
1329 return ldb_next_request(module
, req
);
1334 static int samldb_extended_allocate_rid_pool(struct ldb_module
*module
, struct ldb_request
*req
)
1336 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1337 struct dsdb_fsmo_extended_op
*exop
;
1340 exop
= talloc_get_type(req
->op
.extended
.data
, struct dsdb_fsmo_extended_op
);
1342 ldb_debug(ldb
, LDB_DEBUG_FATAL
, "samldb_extended_allocate_rid_pool: invalid extended data\n");
1343 return LDB_ERR_PROTOCOL_ERROR
;
1346 ret
= ridalloc_allocate_rid_pool_fsmo(module
, exop
);
1347 if (ret
!= LDB_SUCCESS
) {
1351 return ldb_module_done(req
, NULL
, NULL
, LDB_SUCCESS
);
1354 static int samldb_extended(struct ldb_module
*module
, struct ldb_request
*req
)
1356 if (strcmp(req
->op
.extended
.oid
, DSDB_EXTENDED_ALLOCATE_RID_POOL
) == 0) {
1357 return samldb_extended_allocate_rid_pool(module
, req
);
1360 return ldb_next_request(module
, req
);
1364 _PUBLIC_
const struct ldb_module_ops ldb_samldb_module_ops
= {
1367 .modify
= samldb_modify
,
1368 .del
= samldb_delete
,
1369 .extended
= samldb_extended