4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5 Copyright (C) Simo Sorce 2004-2008
6 Copyright (C) Matthias Dieter Wallnöfer 2009
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 "libcli/security/security.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "../lib/util/util_ldb.h"
43 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
46 struct samldb_step *next;
51 struct ldb_module *module;
52 struct ldb_request *req;
54 /* used for add operations */
57 /* the resulting message */
58 struct ldb_message *msg;
60 /* used to find parent domain */
61 struct ldb_dn *check_dn;
62 struct ldb_dn *domain_dn;
63 struct dom_sid *domain_sid;
66 /* holds the entry SID */
69 /* holds a generic dn */
72 /* used in conjunction with "sid" in "samldb_dn_from_sid" */
73 struct ldb_dn *res_dn;
75 /* used in conjunction with "dn" in "samldb_sid_from_dn" */
76 struct dom_sid *res_sid;
78 /* used in "samldb_user_dn_to_prim_group_rid" */
79 uint32_t prim_group_rid;
81 /* used in conjunction with "prim_group_rid" in
82 * "samldb_prim_group_rid_to_users_cnt" */
83 unsigned int users_cnt;
85 /* used in "samldb_group_add_member" and "samldb_group_del_member" */
86 struct ldb_dn *group_dn;
87 struct ldb_dn *member_dn;
89 /* used in "samldb_primary_group_change" */
90 struct ldb_dn *user_dn;
91 struct ldb_dn *old_prim_group_dn, *new_prim_group_dn;
93 /* generic counter - used in "samldb_member_check" */
96 /* all the async steps necessary to complete the operation */
97 struct samldb_step *steps;
98 struct samldb_step *curstep;
101 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
102 struct ldb_request *req)
104 struct ldb_context *ldb;
105 struct samldb_ctx *ac;
107 ldb = ldb_module_get_ctx(module);
109 ac = talloc_zero(req, struct samldb_ctx);
121 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
123 struct samldb_step *step, *stepper;
125 step = talloc_zero(ac, struct samldb_step);
127 return LDB_ERR_OPERATIONS_ERROR;
132 if (ac->steps == NULL) {
136 if (ac->curstep == NULL)
137 return LDB_ERR_OPERATIONS_ERROR;
138 for (stepper = ac->curstep; stepper->next != NULL;
139 stepper = stepper->next);
140 stepper->next = step;
146 static int samldb_first_step(struct samldb_ctx *ac)
148 if (ac->steps == NULL) {
149 return LDB_ERR_OPERATIONS_ERROR;
152 ac->curstep = ac->steps;
153 return ac->curstep->fn(ac);
156 static int samldb_next_step(struct samldb_ctx *ac)
158 if (ac->curstep->next) {
159 ac->curstep = ac->curstep->next;
160 return ac->curstep->fn(ac);
163 /* it is an error if the last step does not properly
164 * return to the upper module by itself */
165 return LDB_ERR_OPERATIONS_ERROR;
169 * samldb_get_parent_domain (async)
172 static int samldb_get_parent_domain(struct samldb_ctx *ac);
174 static int samldb_get_parent_domain_callback(struct ldb_request *req,
175 struct ldb_reply *ares)
177 struct ldb_context *ldb;
178 struct samldb_ctx *ac;
182 ac = talloc_get_type(req->context, struct samldb_ctx);
183 ldb = ldb_module_get_ctx(ac->module);
186 ret = LDB_ERR_OPERATIONS_ERROR;
189 if (ares->error != LDB_SUCCESS) {
190 return ldb_module_done(ac->req, ares->controls,
191 ares->response, ares->error);
194 switch (ares->type) {
195 case LDB_REPLY_ENTRY:
197 if ((ac->domain_dn != NULL) || (ac->domain_sid != NULL)) {
199 ldb_set_errstring(ldb,
200 "Invalid number of results while searching "
201 "for domain object!");
202 ret = LDB_ERR_OPERATIONS_ERROR;
206 nextRid = ldb_msg_find_attr_as_string(ares->message,
208 if (nextRid == NULL) {
209 ldb_asprintf_errstring(ldb,
210 "While looking for domain above %s attribute nextRid not found in %s!\n",
211 ldb_dn_get_linearized(
212 ac->req->op.add.message->dn),
213 ldb_dn_get_linearized(ares->message->dn));
214 ret = LDB_ERR_OPERATIONS_ERROR;
218 ac->next_rid = strtol(nextRid, NULL, 0);
220 ac->domain_sid = samdb_result_dom_sid(ac, ares->message,
222 if (ac->domain_sid == NULL) {
223 ldb_set_errstring(ldb,
224 "Unable to get the parent domain SID!\n");
225 ret = LDB_ERR_CONSTRAINT_VIOLATION;
228 ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
234 case LDB_REPLY_REFERRAL:
242 if ((ac->domain_dn == NULL) || (ac->domain_sid == NULL)) {
243 /* not found -> retry */
244 ret = samldb_get_parent_domain(ac);
247 ret = samldb_next_step(ac);
253 if (ret != LDB_SUCCESS) {
254 return ldb_module_done(ac->req, NULL, NULL, ret);
260 /* Find a domain object in the parents of a particular DN. */
261 static int samldb_get_parent_domain(struct samldb_ctx *ac)
263 struct ldb_context *ldb;
264 static const char * const attrs[] = { "objectSid", "nextRid", NULL };
265 struct ldb_request *req;
269 ldb = ldb_module_get_ctx(ac->module);
271 if (ac->check_dn == NULL) {
272 return LDB_ERR_OPERATIONS_ERROR;
275 dn = ldb_dn_get_parent(ac, ac->check_dn);
277 ldb_set_errstring(ldb,
278 "Unable to find parent domain object!");
279 return LDB_ERR_CONSTRAINT_VIOLATION;
284 ret = ldb_build_search_req(&req, ldb, ac,
286 "(|(objectClass=domain)"
287 "(objectClass=builtinDomain)"
288 "(objectClass=samba4LocalDomain))",
291 ac, samldb_get_parent_domain_callback,
294 if (ret != LDB_SUCCESS) {
298 return ldb_next_request(ac->module, req);
302 static int samldb_generate_samAccountName(struct ldb_message *msg)
306 /* Format: $000000-000000000000 */
308 name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
309 (unsigned int)generate_random(),
310 (unsigned int)generate_random(),
311 (unsigned int)generate_random());
313 return LDB_ERR_OPERATIONS_ERROR;
315 return ldb_msg_add_steal_string(msg, "samAccountName", name);
319 * samldb_check_samAccountName (async)
322 static int samldb_check_samAccountName_callback(struct ldb_request *req,
323 struct ldb_reply *ares)
325 struct samldb_ctx *ac;
328 ac = talloc_get_type(req->context, struct samldb_ctx);
330 if (ares->error != LDB_SUCCESS) {
331 return ldb_module_done(ac->req, ares->controls,
332 ares->response, ares->error);
335 switch (ares->type) {
336 case LDB_REPLY_ENTRY:
337 /* if we get an entry it means this samAccountName
339 return ldb_module_done(ac->req, NULL, NULL,
340 LDB_ERR_ENTRY_ALREADY_EXISTS);
342 case LDB_REPLY_REFERRAL:
343 /* this should not happen */
344 return ldb_module_done(ac->req, NULL, NULL,
345 LDB_ERR_OPERATIONS_ERROR);
348 /* not found, go on */
350 ret = samldb_next_step(ac);
354 if (ret != LDB_SUCCESS) {
355 return ldb_module_done(ac->req, NULL, NULL, ret);
361 static int samldb_check_samAccountName(struct samldb_ctx *ac)
363 struct ldb_context *ldb;
364 struct ldb_request *req;
369 ldb = ldb_module_get_ctx(ac->module);
371 if (ldb_msg_find_element(ac->msg, "samAccountName") == NULL) {
372 ret = samldb_generate_samAccountName(ac->msg);
373 if (ret != LDB_SUCCESS) {
378 name = ldb_msg_find_attr_as_string(ac->msg, "samAccountName", NULL);
380 return LDB_ERR_OPERATIONS_ERROR;
382 filter = talloc_asprintf(ac, "samAccountName=%s", ldb_binary_encode_string(ac, name));
383 if (filter == NULL) {
384 return LDB_ERR_OPERATIONS_ERROR;
387 ret = ldb_build_search_req(&req, ldb, ac,
388 ac->domain_dn, LDB_SCOPE_SUBTREE,
391 ac, samldb_check_samAccountName_callback,
394 if (ret != LDB_SUCCESS) {
397 return ldb_next_request(ac->module, req);
401 static int samldb_check_samAccountType(struct samldb_ctx *ac)
403 struct ldb_context *ldb;
404 unsigned int account_type;
405 unsigned int group_type;
409 ldb = ldb_module_get_ctx(ac->module);
411 /* make sure sAMAccountType is not specified */
412 if (ldb_msg_find_element(ac->msg, "sAMAccountType") != NULL) {
413 ldb_asprintf_errstring(ldb,
414 "sAMAccountType must not be specified!");
415 return LDB_ERR_UNWILLING_TO_PERFORM;
418 if (strcmp("user", ac->type) == 0) {
419 uac = samdb_result_uint(ac->msg, "userAccountControl", 0);
421 ldb_asprintf_errstring(ldb,
422 "userAccountControl invalid!");
423 return LDB_ERR_UNWILLING_TO_PERFORM;
425 account_type = ds_uf2atype(uac);
426 ret = samdb_msg_add_uint(ldb,
430 if (ret != LDB_SUCCESS) {
435 if (strcmp("group", ac->type) == 0) {
437 group_type = samdb_result_uint(ac->msg, "groupType", 0);
438 if (group_type == 0) {
439 ldb_asprintf_errstring(ldb,
440 "groupType invalid!");
441 return LDB_ERR_UNWILLING_TO_PERFORM;
443 account_type = ds_gtype2atype(group_type);
444 ret = samdb_msg_add_uint(ldb,
448 if (ret != LDB_SUCCESS) {
454 return samldb_next_step(ac);
459 * samldb_get_sid_domain (async)
462 static int samldb_get_sid_domain_callback(struct ldb_request *req,
463 struct ldb_reply *ares)
465 struct ldb_context *ldb;
466 struct samldb_ctx *ac;
470 ac = talloc_get_type(req->context, struct samldb_ctx);
471 ldb = ldb_module_get_ctx(ac->module);
474 ret = LDB_ERR_OPERATIONS_ERROR;
477 if (ares->error != LDB_SUCCESS) {
478 return ldb_module_done(ac->req, ares->controls,
479 ares->response, ares->error);
482 switch (ares->type) {
483 case LDB_REPLY_ENTRY:
485 if (ac->next_rid != 0) {
487 ldb_set_errstring(ldb,
488 "Invalid number of results while searching "
489 "for domain object!");
490 ret = LDB_ERR_OPERATIONS_ERROR;
494 nextRid = ldb_msg_find_attr_as_string(ares->message,
496 if (nextRid == NULL) {
497 ldb_asprintf_errstring(ldb,
498 "Attribute nextRid not found in %s!\n",
499 ldb_dn_get_linearized(ares->message->dn));
500 ret = LDB_ERR_OPERATIONS_ERROR;
504 ac->next_rid = strtol(nextRid, NULL, 0);
506 ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
512 case LDB_REPLY_REFERRAL:
520 if (ac->next_rid == 0) {
521 ldb_asprintf_errstring(ldb,
522 "Unable to get nextRid from domain entry!\n");
523 ret = LDB_ERR_OPERATIONS_ERROR;
528 ret = samldb_next_step(ac);
533 if (ret != LDB_SUCCESS) {
534 return ldb_module_done(ac->req, NULL, NULL, ret);
540 /* Find a domain object in the parents of a particular DN. */
541 static int samldb_get_sid_domain(struct samldb_ctx *ac)
543 struct ldb_context *ldb;
544 static const char * const attrs[2] = { "nextRid", NULL };
545 struct ldb_request *req;
549 ldb = ldb_module_get_ctx(ac->module);
551 if (ac->sid == NULL) {
552 return LDB_ERR_OPERATIONS_ERROR;
555 ac->domain_sid = dom_sid_dup(ac, ac->sid);
556 if (!ac->domain_sid) {
557 return LDB_ERR_OPERATIONS_ERROR;
559 /* get the domain component part of the provided SID */
560 ac->domain_sid->num_auths--;
562 filter = talloc_asprintf(ac, "(&(objectSid=%s)"
563 "(|(objectClass=domain)"
564 "(objectClass=builtinDomain)"
565 "(objectClass=samba4LocalDomain)))",
566 ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
567 if (filter == NULL) {
568 return LDB_ERR_OPERATIONS_ERROR;
571 ret = ldb_build_search_req(&req, ldb, ac,
572 ldb_get_default_basedn(ldb),
576 ac, samldb_get_sid_domain_callback,
579 if (ret != LDB_SUCCESS) {
584 return ldb_next_request(ac->module, req);
588 * samldb_dn_from_sid (async)
591 static int samldb_dn_from_sid(struct samldb_ctx *ac);
593 static int samldb_dn_from_sid_callback(struct ldb_request *req,
594 struct ldb_reply *ares)
596 struct ldb_context *ldb;
597 struct samldb_ctx *ac;
600 ac = talloc_get_type(req->context, struct samldb_ctx);
601 ldb = ldb_module_get_ctx(ac->module);
604 ret = LDB_ERR_OPERATIONS_ERROR;
607 if (ares->error != LDB_SUCCESS) {
608 return ldb_module_done(ac->req, ares->controls,
609 ares->response, ares->error);
612 switch (ares->type) {
613 case LDB_REPLY_ENTRY:
615 if (ac->res_dn != NULL) {
617 ldb_set_errstring(ldb,
618 "Invalid number of results while searching "
619 "for domain objects!");
620 ret = LDB_ERR_OPERATIONS_ERROR;
623 ac->res_dn = ldb_dn_copy(ac, ares->message->dn);
629 case LDB_REPLY_REFERRAL:
638 /* found or not found, go on */
639 ret = samldb_next_step(ac);
644 if (ret != LDB_SUCCESS) {
645 return ldb_module_done(ac->req, NULL, NULL, ret);
651 /* Finds the DN "res_dn" of an object with a given SID "sid" */
652 static int samldb_dn_from_sid(struct samldb_ctx *ac)
654 struct ldb_context *ldb;
655 static const char * const attrs[] = { NULL };
656 struct ldb_request *req;
660 ldb = ldb_module_get_ctx(ac->module);
663 return LDB_ERR_OPERATIONS_ERROR;
665 filter = talloc_asprintf(ac, "(objectSid=%s)",
666 ldap_encode_ndr_dom_sid(ac, ac->sid));
668 return LDB_ERR_OPERATIONS_ERROR;
670 ret = ldb_build_search_req(&req, ldb, ac,
671 ldb_get_default_basedn(ldb),
675 ac, samldb_dn_from_sid_callback,
677 if (ret != LDB_SUCCESS)
680 return ldb_next_request(ac->module, req);
684 static int samldb_check_primaryGroupID_1(struct samldb_ctx *ac)
686 struct ldb_context *ldb;
689 ldb = ldb_module_get_ctx(ac->module);
691 rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
692 ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
694 return LDB_ERR_OPERATIONS_ERROR;
697 return samldb_next_step(ac);
700 static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
702 if (ac->res_dn == NULL)
703 return LDB_ERR_UNWILLING_TO_PERFORM;
705 return samldb_next_step(ac);
709 static bool samldb_msg_add_sid(struct ldb_message *msg,
711 const struct dom_sid *sid)
714 enum ndr_err_code ndr_err;
716 ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
717 (ndr_push_flags_fn_t)ndr_push_dom_sid);
718 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
721 return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
724 static int samldb_new_sid(struct samldb_ctx *ac)
727 if (ac->domain_sid == NULL || ac->next_rid == 0) {
728 return LDB_ERR_OPERATIONS_ERROR;
731 ac->sid = dom_sid_add_rid(ac, ac->domain_sid, ac->next_rid + 1);
732 if (ac->sid == NULL) {
733 return LDB_ERR_OPERATIONS_ERROR;
736 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
737 return LDB_ERR_OPERATIONS_ERROR;
740 return samldb_next_step(ac);
744 * samldb_notice_sid_callback (async)
747 static int samldb_notice_sid_callback(struct ldb_request *req,
748 struct ldb_reply *ares)
750 struct ldb_context *ldb;
751 struct samldb_ctx *ac;
754 ac = talloc_get_type(req->context, struct samldb_ctx);
755 ldb = ldb_module_get_ctx(ac->module);
758 ret = LDB_ERR_OPERATIONS_ERROR;
761 if (ares->error != LDB_SUCCESS) {
762 return ldb_module_done(ac->req, ares->controls,
763 ares->response, ares->error);
765 if (ares->type != LDB_REPLY_DONE) {
766 ldb_set_errstring(ldb,
767 "Invalid reply type!\n");
768 ret = LDB_ERR_OPERATIONS_ERROR;
772 ret = samldb_next_step(ac);
775 if (ret != LDB_SUCCESS) {
776 return ldb_module_done(ac->req, NULL, NULL, ret);
782 /* If we are adding new users/groups, we need to update the nextRid
783 * attribute to be 'above' the new/incoming RID. Attempt to do it
785 static int samldb_notice_sid(struct samldb_ctx *ac)
787 struct ldb_context *ldb;
788 uint32_t old_id, new_id;
789 struct ldb_request *req;
790 struct ldb_message *msg;
791 struct ldb_message_element *els;
792 struct ldb_val *vals;
795 ldb = ldb_module_get_ctx(ac->module);
796 old_id = ac->next_rid;
797 new_id = ac->sid->sub_auths[ac->sid->num_auths - 1];
799 if (old_id >= new_id) {
800 /* no need to update the domain nextRid attribute */
801 return samldb_next_step(ac);
804 /* we do a delete and add as a single operation. That prevents
805 a race, in case we are not actually on a transaction db */
806 msg = ldb_msg_new(ac);
809 return LDB_ERR_OPERATIONS_ERROR;
811 els = talloc_array(msg, struct ldb_message_element, 2);
814 return LDB_ERR_OPERATIONS_ERROR;
816 vals = talloc_array(msg, struct ldb_val, 2);
819 return LDB_ERR_OPERATIONS_ERROR;
821 msg->dn = ac->domain_dn;
822 msg->num_elements = 2;
825 els[0].num_values = 1;
826 els[0].values = &vals[0];
827 els[0].flags = LDB_FLAG_MOD_DELETE;
828 els[0].name = talloc_strdup(msg, "nextRid");
831 return LDB_ERR_OPERATIONS_ERROR;
834 els[1].num_values = 1;
835 els[1].values = &vals[1];
836 els[1].flags = LDB_FLAG_MOD_ADD;
837 els[1].name = els[0].name;
839 vals[0].data = (uint8_t *)talloc_asprintf(vals, "%u", old_id);
842 return LDB_ERR_OPERATIONS_ERROR;
844 vals[0].length = strlen((char *)vals[0].data);
846 vals[1].data = (uint8_t *)talloc_asprintf(vals, "%u", new_id);
849 return LDB_ERR_OPERATIONS_ERROR;
851 vals[1].length = strlen((char *)vals[1].data);
853 ret = ldb_build_mod_req(&req, ldb, ac,
855 ac, samldb_notice_sid_callback,
857 if (ret != LDB_SUCCESS) {
861 return ldb_next_request(ac->module, req);
865 * samldb_add_entry (async)
868 static int samldb_add_entry_callback(struct ldb_request *req,
869 struct ldb_reply *ares)
871 struct ldb_context *ldb;
872 struct samldb_ctx *ac;
874 ac = talloc_get_type(req->context, struct samldb_ctx);
875 ldb = ldb_module_get_ctx(ac->module);
878 return ldb_module_done(ac->req, NULL, NULL,
879 LDB_ERR_OPERATIONS_ERROR);
881 if (ares->error != LDB_SUCCESS) {
882 return ldb_module_done(ac->req, ares->controls,
883 ares->response, ares->error);
885 if (ares->type != LDB_REPLY_DONE) {
886 ldb_set_errstring(ldb,
887 "Invalid reply type!\n");
888 return ldb_module_done(ac->req, NULL, NULL,
889 LDB_ERR_OPERATIONS_ERROR);
892 /* we exit the samldb module here */
893 return ldb_module_done(ac->req, ares->controls,
894 ares->response, LDB_SUCCESS);
897 static int samldb_add_entry(struct samldb_ctx *ac)
899 struct ldb_context *ldb;
900 struct ldb_request *req;
903 ldb = ldb_module_get_ctx(ac->module);
905 ret = ldb_build_add_req(&req, ldb, ac,
908 ac, samldb_add_entry_callback,
910 if (ret != LDB_SUCCESS) {
914 return ldb_next_request(ac->module, req);
918 static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
920 struct ldb_context *ldb;
923 ldb = ldb_module_get_ctx(ac->module);
925 /* search for a parent domain objet */
926 ac->check_dn = ac->req->op.add.message->dn;
927 ret = samldb_add_step(ac, samldb_get_parent_domain);
928 if (ret != LDB_SUCCESS) return ret;
930 /* Add informations for the different account types */
932 if (strcmp(ac->type, "user") == 0) {
933 ret = samdb_find_or_add_attribute(ldb, ac->msg,
934 "userAccountControl", "546");
935 if (ret != LDB_SUCCESS) return ret;
936 ret = samdb_find_or_add_attribute(ldb, ac->msg,
938 if (ret != LDB_SUCCESS) return ret;
939 ret = samdb_find_or_add_attribute(ldb, ac->msg,
941 if (ret != LDB_SUCCESS) return ret;
942 ret = samdb_find_or_add_attribute(ldb, ac->msg,
944 if (ret != LDB_SUCCESS) return ret;
945 ret = samdb_find_or_add_attribute(ldb, ac->msg,
946 "badPasswordTime", "0");
947 if (ret != LDB_SUCCESS) return ret;
948 ret = samdb_find_or_add_attribute(ldb, ac->msg,
950 if (ret != LDB_SUCCESS) return ret;
951 ret = samdb_find_or_add_attribute(ldb, ac->msg,
953 if (ret != LDB_SUCCESS) return ret;
954 ret = samdb_find_or_add_attribute(ldb, ac->msg,
956 if (ret != LDB_SUCCESS) return ret;
957 ret = samdb_find_or_add_attribute(ldb, ac->msg,
958 "primaryGroupID", "513");
959 if (ret != LDB_SUCCESS) return ret;
960 ret = samdb_find_or_add_attribute(ldb, ac->msg,
961 "accountExpires", "9223372036854775807");
962 if (ret != LDB_SUCCESS) return ret;
963 ret = samdb_find_or_add_attribute(ldb, ac->msg,
965 if (ret != LDB_SUCCESS) return ret;
966 } else if (strcmp(ac->type, "group") == 0) {
967 ret = samdb_find_or_add_attribute(ldb, ac->msg,
968 "groupType", "-2147483646");
969 if (ret != LDB_SUCCESS) return ret;
971 /* we should only have "user" and "group" */
972 ldb_asprintf_errstring(ldb,
973 "Invalid entry type!\n");
974 return LDB_ERR_OPERATIONS_ERROR;
977 /* check if we have a valid samAccountName */
978 ret = samldb_add_step(ac, samldb_check_samAccountName);
979 if (ret != LDB_SUCCESS) return ret;
981 /* check account_type/group_type */
982 ret = samldb_add_step(ac, samldb_check_samAccountType);
983 if (ret != LDB_SUCCESS) return ret;
985 /* check if we have a valid primary group ID */
986 if (strcmp(ac->type, "user") == 0) {
987 ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
988 if (ret != LDB_SUCCESS) return ret;
989 ret = samldb_add_step(ac, samldb_dn_from_sid);
990 if (ret != LDB_SUCCESS) return ret;
991 ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
992 if (ret != LDB_SUCCESS) return ret;
995 /* check if we have a valid SID */
996 ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
998 ret = samldb_add_step(ac, samldb_new_sid);
999 if (ret != LDB_SUCCESS) return ret;
1001 ret = samldb_add_step(ac, samldb_get_sid_domain);
1002 if (ret != LDB_SUCCESS) return ret;
1005 ret = samldb_add_step(ac, samldb_notice_sid);
1006 if (ret != LDB_SUCCESS) return ret;
1008 /* finally proceed with adding the entry */
1009 ret = samldb_add_step(ac, samldb_add_entry);
1010 if (ret != LDB_SUCCESS) return ret;
1012 return samldb_first_step(ac);
1016 * samldb_foreign_notice_sid (async)
1019 static int samldb_foreign_notice_sid_callback(struct ldb_request *req,
1020 struct ldb_reply *ares)
1022 struct ldb_context *ldb;
1023 struct samldb_ctx *ac;
1024 const char *nextRid;
1028 ac = talloc_get_type(req->context, struct samldb_ctx);
1029 ldb = ldb_module_get_ctx(ac->module);
1032 ret = LDB_ERR_OPERATIONS_ERROR;
1035 if (ares->error != LDB_SUCCESS) {
1036 return ldb_module_done(ac->req, ares->controls,
1037 ares->response, ares->error);
1040 switch (ares->type) {
1041 case LDB_REPLY_ENTRY:
1043 if (ac->next_rid != 0) {
1045 ldb_set_errstring(ldb,
1046 "Invalid number of results while searching "
1047 "for domain object!");
1048 ret = LDB_ERR_OPERATIONS_ERROR;
1052 nextRid = ldb_msg_find_attr_as_string(ares->message,
1054 if (nextRid == NULL) {
1055 ldb_asprintf_errstring(ldb,
1056 "while looking for forign sid %s attribute nextRid not found in %s\n",
1057 dom_sid_string(ares, ac->sid),
1058 ldb_dn_get_linearized(ares->message->dn));
1059 ret = LDB_ERR_OPERATIONS_ERROR;
1063 ac->next_rid = strtol(nextRid, NULL, 0);
1065 ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
1067 name = samdb_result_string(ares->message, "name", NULL);
1068 ldb_debug(ldb, LDB_DEBUG_TRACE,
1069 "NOTE (strange but valid): Adding foreign SID "
1070 "record with SID %s, but this domain (%s) is "
1071 "not foreign in the database",
1072 dom_sid_string(ares, ac->sid), name);
1078 case LDB_REPLY_REFERRAL:
1084 case LDB_REPLY_DONE:
1087 /* if this is a fake foreign SID, notice the SID */
1088 if (ac->domain_dn) {
1089 ret = samldb_notice_sid(ac);
1094 ret = samldb_next_step(ac);
1099 if (ret != LDB_SUCCESS) {
1100 return ldb_module_done(ac->req, NULL, NULL, ret);
1106 /* Find a domain object in the parents of a particular DN. */
1107 static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
1109 struct ldb_context *ldb;
1110 static const char * const attrs[3] = { "nextRid", "name", NULL };
1111 struct ldb_request *req;
1116 ldb = ldb_module_get_ctx(ac->module);
1118 if (ac->sid == NULL) {
1119 return LDB_ERR_OPERATIONS_ERROR;
1122 status = dom_sid_split_rid(ac, ac->sid, &ac->domain_sid, NULL);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 return LDB_ERR_OPERATIONS_ERROR;
1127 filter = talloc_asprintf(ac, "(&(objectSid=%s)(objectclass=domain))",
1128 ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
1129 if (filter == NULL) {
1130 return LDB_ERR_OPERATIONS_ERROR;
1133 ret = ldb_build_search_req(&req, ldb, ac,
1134 ldb_get_default_basedn(ldb),
1138 ac, samldb_foreign_notice_sid_callback,
1141 if (ret != LDB_SUCCESS) {
1145 return ldb_next_request(ac->module, req);
1149 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1151 struct ldb_context *ldb;
1154 ldb = ldb_module_get_ctx(ac->module);
1158 ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1159 if (ac->sid == NULL) {
1160 ac->sid = dom_sid_parse_talloc(ac->msg,
1161 (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1163 ldb_set_errstring(ldb,
1164 "No valid SID found in "
1165 "ForeignSecurityPrincipal CN!");
1167 return LDB_ERR_CONSTRAINT_VIOLATION;
1169 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1171 return LDB_ERR_OPERATIONS_ERROR;
1175 /* check if we need to notice this SID */
1176 ret = samldb_add_step(ac, samldb_foreign_notice_sid);
1177 if (ret != LDB_SUCCESS) return ret;
1179 /* finally proceed with adding the entry */
1180 ret = samldb_add_step(ac, samldb_add_entry);
1181 if (ret != LDB_SUCCESS) return ret;
1183 return samldb_first_step(ac);
1186 static int samldb_check_rdn(struct ldb_module *module, struct ldb_dn *dn)
1188 struct ldb_context *ldb;
1189 const char *rdn_name;
1191 ldb = ldb_module_get_ctx(module);
1192 rdn_name = ldb_dn_get_rdn_name(dn);
1194 if (strcasecmp(rdn_name, "cn") != 0) {
1195 ldb_asprintf_errstring(ldb,
1196 "Bad RDN (%s=) for samldb object, "
1197 "should be CN=!\n", rdn_name);
1198 return LDB_ERR_CONSTRAINT_VIOLATION;
1205 * samldb_sid_from_dn (async)
1208 static int samldb_sid_from_dn(struct samldb_ctx *ac);
1210 static int samldb_sid_from_dn_callback(struct ldb_request *req,
1211 struct ldb_reply *ares)
1213 struct ldb_context *ldb;
1214 struct samldb_ctx *ac;
1217 ac = talloc_get_type(req->context, struct samldb_ctx);
1218 ldb = ldb_module_get_ctx(ac->module);
1221 ret = LDB_ERR_OPERATIONS_ERROR;
1224 if (ares->error != LDB_SUCCESS) {
1225 return ldb_module_done(ac->req, ares->controls,
1226 ares->response, ares->error);
1229 switch (ares->type) {
1230 case LDB_REPLY_ENTRY:
1232 if (ac->res_sid != NULL) {
1234 ldb_set_errstring(ldb,
1235 "Invalid number of results while searching "
1236 "for domain objects!");
1237 ret = LDB_ERR_OPERATIONS_ERROR;
1240 ac->res_sid = samdb_result_dom_sid(ac, ares->message,
1247 case LDB_REPLY_REFERRAL:
1253 case LDB_REPLY_DONE:
1256 /* found or not found, go on */
1257 ret = samldb_next_step(ac);
1262 if (ret != LDB_SUCCESS) {
1263 return ldb_module_done(ac->req, NULL, NULL, ret);
1269 /* Finds the SID "res_sid" of an object with a given DN "dn" */
1270 static int samldb_sid_from_dn(struct samldb_ctx *ac)
1272 struct ldb_context *ldb;
1273 static const char * const attrs[] = { "objectSid" };
1274 struct ldb_request *req;
1277 ldb = ldb_module_get_ctx(ac->module);
1280 return LDB_ERR_OPERATIONS_ERROR;
1282 ret = ldb_build_search_req(&req, ldb, ac,
1287 ac, samldb_sid_from_dn_callback,
1289 if (ret != LDB_SUCCESS)
1292 return ldb_next_request(ac->module, req);
1296 * samldb_user_dn_to_prim_group_rid (async)
1299 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
1301 static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
1302 struct ldb_reply *ares)
1304 struct ldb_context *ldb;
1305 struct samldb_ctx *ac;
1308 ac = talloc_get_type(req->context, struct samldb_ctx);
1309 ldb = ldb_module_get_ctx(ac->module);
1312 ret = LDB_ERR_OPERATIONS_ERROR;
1315 if (ares->error != LDB_SUCCESS) {
1316 return ldb_module_done(ac->req, ares->controls,
1317 ares->response, ares->error);
1320 switch (ares->type) {
1321 case LDB_REPLY_ENTRY:
1323 if (ac->prim_group_rid != 0) {
1325 ldb_set_errstring(ldb,
1326 "Invalid number of results while searching "
1327 "for domain objects!");
1328 ret = LDB_ERR_OPERATIONS_ERROR;
1331 ac->prim_group_rid = samdb_result_uint(ares->message,
1332 "primaryGroupID", ~0);
1338 case LDB_REPLY_REFERRAL:
1344 case LDB_REPLY_DONE:
1346 if (ac->prim_group_rid == 0) {
1347 ldb_asprintf_errstring(ldb,
1348 "Unable to get the primary group RID!\n");
1349 ret = LDB_ERR_OPERATIONS_ERROR;
1354 ret = samldb_next_step(ac);
1359 if (ret != LDB_SUCCESS) {
1360 return ldb_module_done(ac->req, NULL, NULL, ret);
1366 /* Locates the "primaryGroupID" attribute from a certain user specified as
1367 * "user_dn". Saves the result in "prim_group_rid". */
1368 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
1370 struct ldb_context *ldb;
1371 static const char * const attrs[] = { "primaryGroupID", NULL };
1372 struct ldb_request *req;
1375 ldb = ldb_module_get_ctx(ac->module);
1377 if (ac->user_dn == NULL)
1378 return LDB_ERR_OPERATIONS_ERROR;
1380 ret = ldb_build_search_req(&req, ldb, ac,
1385 ac, samldb_user_dn_to_prim_group_rid_callback,
1387 if (ret != LDB_SUCCESS)
1390 return ldb_next_request(ac->module, req);
1394 * samldb_prim_group_rid_to_users_cnt (async)
1397 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac);
1399 static int samldb_prim_group_rid_to_users_cnt_callback(struct ldb_request *req,
1400 struct ldb_reply *ares)
1402 struct ldb_context *ldb;
1403 struct samldb_ctx *ac;
1406 ac = talloc_get_type(req->context, struct samldb_ctx);
1407 ldb = ldb_module_get_ctx(ac->module);
1410 ret = LDB_ERR_OPERATIONS_ERROR;
1413 if (ares->error != LDB_SUCCESS) {
1414 return ldb_module_done(ac->req, ares->controls,
1415 ares->response, ares->error);
1418 switch (ares->type) {
1419 case LDB_REPLY_ENTRY:
1427 case LDB_REPLY_REFERRAL:
1433 case LDB_REPLY_DONE:
1436 /* found or not found, go on */
1437 ret = samldb_next_step(ac);
1442 if (ret != LDB_SUCCESS) {
1443 return ldb_module_done(ac->req, NULL, NULL, ret);
1449 /* Finds the amount of users which have the primary group "prim_group_rid" and
1450 * save the result in "users_cnt" */
1451 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac)
1453 struct ldb_context *ldb;
1454 static const char * const attrs[] = { NULL };
1455 struct ldb_request *req;
1459 ldb = ldb_module_get_ctx(ac->module);
1461 if ((ac->prim_group_rid == 0) || (ac->users_cnt != 0))
1462 return LDB_ERR_OPERATIONS_ERROR;
1464 filter = talloc_asprintf(ac, "(&(primaryGroupID=%u)(objectclass=user))",
1465 ac->prim_group_rid);
1467 return LDB_ERR_OPERATIONS_ERROR;
1469 ret = ldb_build_search_req(&req, ldb, ac,
1470 ldb_get_default_basedn(ldb),
1475 samldb_prim_group_rid_to_users_cnt_callback,
1477 if (ret != LDB_SUCCESS)
1480 return ldb_next_request(ac->module, req);
1484 * samldb_group_add_member (async)
1485 * samldb_group_del_member (async)
1488 static int samldb_group_add_del_member_callback(struct ldb_request *req,
1489 struct ldb_reply *ares)
1491 struct ldb_context *ldb;
1492 struct samldb_ctx *ac;
1495 ac = talloc_get_type(req->context, struct samldb_ctx);
1496 ldb = ldb_module_get_ctx(ac->module);
1499 ret = LDB_ERR_OPERATIONS_ERROR;
1502 if (ares->error != LDB_SUCCESS) {
1503 if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1504 /* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
1505 * "member" attribute) return "UNWILLING_TO_PERFORM" */
1506 ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
1508 return ldb_module_done(ac->req, ares->controls,
1509 ares->response, ares->error);
1511 if (ares->type != LDB_REPLY_DONE) {
1512 ldb_set_errstring(ldb,
1513 "Invalid reply type!\n");
1514 ret = LDB_ERR_OPERATIONS_ERROR;
1518 ret = samldb_next_step(ac);
1521 if (ret != LDB_SUCCESS) {
1522 return ldb_module_done(ac->req, NULL, NULL, ret);
1528 /* Adds a member with DN "member_dn" to a group with DN "group_dn" */
1529 static int samldb_group_add_member(struct samldb_ctx *ac)
1531 struct ldb_context *ldb;
1532 struct ldb_request *req;
1533 struct ldb_message *msg;
1536 ldb = ldb_module_get_ctx(ac->module);
1538 if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1539 return LDB_ERR_OPERATIONS_ERROR;
1541 msg = ldb_msg_new(ac);
1542 msg->dn = ac->group_dn;
1543 samdb_msg_add_addval(ldb, ac, msg, "member",
1544 ldb_dn_get_linearized(ac->member_dn));
1546 ret = ldb_build_mod_req(&req, ldb, ac,
1548 ac, samldb_group_add_del_member_callback,
1550 if (ret != LDB_SUCCESS)
1553 return ldb_next_request(ac->module, req);
1556 /* Removes a member with DN "member_dn" from a group with DN "group_dn" */
1557 static int samldb_group_del_member(struct samldb_ctx *ac)
1559 struct ldb_context *ldb;
1560 struct ldb_request *req;
1561 struct ldb_message *msg;
1564 ldb = ldb_module_get_ctx(ac->module);
1566 if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1567 return LDB_ERR_OPERATIONS_ERROR;
1569 msg = ldb_msg_new(ac);
1570 msg->dn = ac->group_dn;
1571 samdb_msg_add_delval(ldb, ac, msg, "member",
1572 ldb_dn_get_linearized(ac->member_dn));
1574 ret = ldb_build_mod_req(&req, ldb, ac,
1576 ac, samldb_group_add_del_member_callback,
1578 if (ret != LDB_SUCCESS)
1581 return ldb_next_request(ac->module, req);
1585 static int samldb_prim_group_change_1(struct samldb_ctx *ac)
1587 struct ldb_context *ldb;
1590 ldb = ldb_module_get_ctx(ac->module);
1592 ac->user_dn = ac->msg->dn;
1594 rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
1595 ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1596 if (ac->sid == NULL)
1597 return LDB_ERR_OPERATIONS_ERROR;
1600 ac->prim_group_rid = 0;
1602 return samldb_next_step(ac);
1605 static int samldb_prim_group_change_2(struct samldb_ctx *ac)
1607 struct ldb_context *ldb;
1609 ldb = ldb_module_get_ctx(ac->module);
1611 if (ac->res_dn != NULL)
1612 ac->new_prim_group_dn = ac->res_dn;
1614 return LDB_ERR_UNWILLING_TO_PERFORM;
1616 ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1617 ac->prim_group_rid);
1618 if (ac->sid == NULL)
1619 return LDB_ERR_OPERATIONS_ERROR;
1622 return samldb_next_step(ac);
1625 static int samldb_prim_group_change_4(struct samldb_ctx *ac);
1626 static int samldb_prim_group_change_5(struct samldb_ctx *ac);
1627 static int samldb_prim_group_change_6(struct samldb_ctx *ac);
1629 static int samldb_prim_group_change_3(struct samldb_ctx *ac)
1633 if (ac->res_dn != NULL)
1634 ac->old_prim_group_dn = ac->res_dn;
1636 return LDB_ERR_UNWILLING_TO_PERFORM;
1638 /* Only update when the primary group changed */
1639 if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
1640 ac->member_dn = ac->user_dn;
1641 /* Remove the "member" attribute of the actual (new) primary
1644 ret = samldb_add_step(ac, samldb_prim_group_change_4);
1645 if (ret != LDB_SUCCESS) return ret;
1647 ret = samldb_add_step(ac, samldb_group_del_member);
1648 if (ret != LDB_SUCCESS) return ret;
1650 /* Add a "member" attribute for the previous primary group */
1652 ret = samldb_add_step(ac, samldb_prim_group_change_5);
1653 if (ret != LDB_SUCCESS) return ret;
1655 ret = samldb_add_step(ac, samldb_group_add_member);
1656 if (ret != LDB_SUCCESS) return ret;
1659 ret = samldb_add_step(ac, samldb_prim_group_change_6);
1660 if (ret != LDB_SUCCESS) return ret;
1662 return samldb_next_step(ac);
1665 static int samldb_prim_group_change_4(struct samldb_ctx *ac)
1667 ac->group_dn = ac->new_prim_group_dn;
1669 return samldb_next_step(ac);
1672 static int samldb_prim_group_change_5(struct samldb_ctx *ac)
1674 ac->group_dn = ac->old_prim_group_dn;
1676 return samldb_next_step(ac);
1679 static int samldb_prim_group_change_6(struct samldb_ctx *ac)
1681 return ldb_next_request(ac->module, ac->req);
1684 static int samldb_prim_group_change(struct samldb_ctx *ac)
1688 /* Finds out the DN of the new primary group */
1690 ret = samldb_add_step(ac, samldb_prim_group_change_1);
1691 if (ret != LDB_SUCCESS) return ret;
1693 ret = samldb_add_step(ac, samldb_dn_from_sid);
1694 if (ret != LDB_SUCCESS) return ret;
1696 ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1697 if (ret != LDB_SUCCESS) return ret;
1699 /* Finds out the DN of the old primary group */
1701 ret = samldb_add_step(ac, samldb_prim_group_change_2);
1702 if (ret != LDB_SUCCESS) return ret;
1704 ret = samldb_add_step(ac, samldb_dn_from_sid);
1705 if (ret != LDB_SUCCESS) return ret;
1707 ret = samldb_add_step(ac, samldb_prim_group_change_3);
1708 if (ret != LDB_SUCCESS) return ret;
1710 return samldb_first_step(ac);
1714 static int samldb_member_check_1(struct samldb_ctx *ac)
1716 struct ldb_context *ldb;
1717 struct ldb_message_element *el;
1719 ldb = ldb_module_get_ctx(ac->module);
1721 el = ldb_msg_find_element(ac->msg, "member");
1723 ac->user_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[ac->cnt]);
1724 if (!ldb_dn_validate(ac->user_dn))
1725 return LDB_ERR_OPERATIONS_ERROR;
1726 ac->prim_group_rid = 0;
1728 return samldb_next_step(ac);
1731 static int samldb_member_check_2(struct samldb_ctx *ac)
1733 struct ldb_context *ldb;
1735 ldb = ldb_module_get_ctx(ac->module);
1737 ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1738 ac->prim_group_rid);
1739 if (ac->sid == NULL)
1740 return LDB_ERR_OPERATIONS_ERROR;
1743 return samldb_next_step(ac);
1746 static int samldb_member_check_3(struct samldb_ctx *ac)
1748 if (ldb_dn_compare(ac->res_dn, ac->msg->dn) == 0)
1749 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1753 return samldb_next_step(ac);
1756 static int samldb_member_check_4(struct samldb_ctx *ac)
1758 return ldb_next_request(ac->module, ac->req);
1761 static int samldb_member_check(struct samldb_ctx *ac)
1763 struct ldb_message_element *el;
1766 el = ldb_msg_find_element(ac->msg, "member");
1768 for (i = 0; i < el->num_values; i++) {
1769 /* Denies to add "member"s to groups which are primary ones
1771 ret = samldb_add_step(ac, samldb_member_check_1);
1772 if (ret != LDB_SUCCESS) return ret;
1774 ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1775 if (ret != LDB_SUCCESS) return ret;
1777 ret = samldb_add_step(ac, samldb_member_check_2);
1778 if (ret != LDB_SUCCESS) return ret;
1780 ret = samldb_add_step(ac, samldb_dn_from_sid);
1781 if (ret != LDB_SUCCESS) return ret;
1783 ret = samldb_add_step(ac, samldb_member_check_3);
1784 if (ret != LDB_SUCCESS) return ret;
1787 ret = samldb_add_step(ac, samldb_member_check_4);
1788 if (ret != LDB_SUCCESS) return ret;
1790 return samldb_first_step(ac);
1794 static int samldb_prim_group_users_check_1(struct samldb_ctx *ac)
1796 ac->dn = ac->req->op.del.dn;
1799 return samldb_next_step(ac);
1802 static int samldb_prim_group_users_check_2(struct samldb_ctx *ac)
1807 if (ac->res_sid == NULL) {
1808 /* No SID - therefore ok here */
1809 return ldb_next_request(ac->module, ac->req);
1811 status = dom_sid_split_rid(ac, ac->res_sid, NULL, &rid);
1812 if (!NT_STATUS_IS_OK(status))
1813 return LDB_ERR_OPERATIONS_ERROR;
1816 /* Special object (security principal?) */
1817 return ldb_next_request(ac->module, ac->req);
1820 ac->prim_group_rid = rid;
1823 return samldb_next_step(ac);
1826 static int samldb_prim_group_users_check_3(struct samldb_ctx *ac)
1828 if (ac->users_cnt > 0)
1829 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1831 return ldb_next_request(ac->module, ac->req);
1834 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
1838 /* Finds out the SID/RID of the domain object */
1840 ret = samldb_add_step(ac, samldb_prim_group_users_check_1);
1841 if (ret != LDB_SUCCESS) return ret;
1843 ret = samldb_add_step(ac, samldb_sid_from_dn);
1844 if (ret != LDB_SUCCESS) return ret;
1846 /* Deny delete requests from groups which are primary ones */
1848 ret = samldb_add_step(ac, samldb_prim_group_users_check_2);
1849 if (ret != LDB_SUCCESS) return ret;
1851 ret = samldb_add_step(ac, samldb_prim_group_rid_to_users_cnt);
1852 if (ret != LDB_SUCCESS) return ret;
1854 ret = samldb_add_step(ac, samldb_prim_group_users_check_3);
1855 if (ret != LDB_SUCCESS) return ret;
1857 return samldb_first_step(ac);
1862 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1864 struct ldb_context *ldb;
1865 struct samldb_ctx *ac;
1868 ldb = ldb_module_get_ctx(module);
1869 ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add_record\n");
1871 /* do not manipulate our control entries */
1872 if (ldb_dn_is_special(req->op.add.message->dn)) {
1873 return ldb_next_request(module, req);
1876 ac = samldb_ctx_init(module, req);
1878 return LDB_ERR_OPERATIONS_ERROR;
1881 /* build the new msg */
1882 ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
1885 ldb_debug(ldb, LDB_DEBUG_FATAL,
1886 "samldb_add: ldb_msg_copy failed!\n");
1887 return LDB_ERR_OPERATIONS_ERROR;
1890 if (samdb_find_attribute(ldb, ac->msg,
1891 "objectclass", "computer") != NULL) {
1893 /* make sure the computer object also has the 'user'
1894 * objectclass so it will be handled by the next call */
1895 ret = samdb_find_or_add_value(ldb, ac->msg,
1896 "objectclass", "user");
1897 if (ret != LDB_SUCCESS) {
1903 if (samdb_find_attribute(ldb, ac->msg,
1904 "objectclass", "user") != NULL) {
1906 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1907 if (ret != LDB_SUCCESS) {
1912 return samldb_fill_object(ac, "user");
1915 if (samdb_find_attribute(ldb, ac->msg,
1916 "objectclass", "group") != NULL) {
1918 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1919 if (ret != LDB_SUCCESS) {
1924 return samldb_fill_object(ac, "group");
1927 /* perhaps a foreignSecurityPrincipal? */
1928 if (samdb_find_attribute(ldb, ac->msg,
1930 "foreignSecurityPrincipal") != NULL) {
1932 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1933 if (ret != LDB_SUCCESS) {
1938 return samldb_fill_foreignSecurityPrincipal_object(ac);
1943 /* nothing matched, go on */
1944 return ldb_next_request(module, req);
1948 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
1950 struct ldb_context *ldb;
1951 struct ldb_message *msg;
1952 struct ldb_message_element *el, *el2;
1954 uint32_t account_type;
1956 if (ldb_dn_is_special(req->op.mod.message->dn)) {
1957 /* do not manipulate our control entries */
1958 return ldb_next_request(module, req);
1961 ldb = ldb_module_get_ctx(module);
1963 if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
1964 ldb_asprintf_errstring(ldb,
1965 "sAMAccountType must not be specified!");
1966 return LDB_ERR_UNWILLING_TO_PERFORM;
1969 /* TODO: do not modify original request, create a new one */
1971 el = ldb_msg_find_element(req->op.mod.message, "groupType");
1972 if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1973 uint32_t group_type;
1975 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1976 req->op.mod.message);
1978 group_type = strtoul((const char *)el->values[0].data, NULL, 0);
1979 account_type = ds_gtype2atype(group_type);
1980 ret = samdb_msg_add_uint(ldb, msg, msg,
1983 if (ret != LDB_SUCCESS) {
1986 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1987 el2->flags = LDB_FLAG_MOD_REPLACE;
1990 el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
1991 if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1992 uint32_t user_account_control;
1994 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1995 req->op.mod.message);
1997 user_account_control = strtoul((const char *)el->values[0].data,
1999 account_type = ds_uf2atype(user_account_control);
2000 ret = samdb_msg_add_uint(ldb, msg, msg,
2003 if (ret != LDB_SUCCESS) {
2006 el2 = ldb_msg_find_element(msg, "sAMAccountType");
2007 el2->flags = LDB_FLAG_MOD_REPLACE;
2009 if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
2010 ret = samdb_msg_add_string(ldb, msg, msg,
2011 "isCriticalSystemObject", "TRUE");
2012 if (ret != LDB_SUCCESS) {
2015 el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
2016 el2->flags = LDB_FLAG_MOD_REPLACE;
2020 el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
2021 if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2022 struct samldb_ctx *ac;
2024 ac = samldb_ctx_init(module, req);
2026 return LDB_ERR_OPERATIONS_ERROR;
2028 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2029 req->op.mod.message);
2031 return samldb_prim_group_change(ac);
2034 el = ldb_msg_find_element(req->op.mod.message, "member");
2035 if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2036 struct samldb_ctx *ac;
2038 ac = samldb_ctx_init(module, req);
2040 return LDB_ERR_OPERATIONS_ERROR;
2042 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2043 req->op.mod.message);
2045 return samldb_member_check(ac);
2048 /* nothing matched, go on */
2049 return ldb_next_request(module, req);
2053 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2055 struct samldb_ctx *ac;
2057 if (ldb_dn_is_special(req->op.del.dn)) {
2058 /* do not manipulate our control entries */
2059 return ldb_next_request(module, req);
2062 ac = samldb_ctx_init(module, req);
2064 return LDB_ERR_OPERATIONS_ERROR;
2066 return samldb_prim_group_users_check(ac);
2070 static int samldb_init(struct ldb_module *module)
2072 return ldb_next_init(module);
2075 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
2077 .init_context = samldb_init,
2079 .modify = samldb_modify,
2080 .del = samldb_delete