smbd: Ensure we grant owner sid in check_parent_access_fsp()
[samba.git] / source4 / dsdb / samdb / ldb_modules / acl.c
1 /*
2   ldb database library
3
4   Copyright (C) Simo Sorce 2006-2008
5   Copyright (C) Nadezhda Ivanova 2009
6   Copyright (C) Anatoliy Atanasov  2009
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  *  Name: ldb
24  *
25  *  Component: ldb ACL module
26  *
27  *  Description: Module that performs authorisation access checks based on the
28  *               account's security context and the DACL of the object being polled.
29  *               Only DACL checks implemented at this point
30  *
31  *  Authors: Nadezhda Ivanova, Anatoliy Atanasov
32  */
33
34 #include "includes.h"
35 #include "ldb_module.h"
36 #include "auth/auth.h"
37 #include "libcli/security/security.h"
38 #include "dsdb/samdb/samdb.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "param/param.h"
41 #include "dsdb/samdb/ldb_modules/util.h"
42 #include "lib/util/tsort.h"
43 #include "system/kerberos.h"
44 #include "auth/kerberos/kerberos.h"
45
46 #undef strcasecmp
47 #undef strncasecmp
48
49 struct acl_private {
50         bool acl_search;
51         const char **password_attrs;
52         void *cached_schema_ptr;
53         uint64_t cached_schema_metadata_usn;
54         uint64_t cached_schema_loaded_usn;
55         const char **confidential_attrs;
56 };
57
58 struct acl_context {
59         struct ldb_module *module;
60         struct ldb_request *req;
61         bool am_system;
62         bool am_administrator;
63         bool constructed_attrs;
64         bool allowedAttributes;
65         bool allowedAttributesEffective;
66         bool allowedChildClasses;
67         bool allowedChildClassesEffective;
68         bool sDRightsEffective;
69         struct dsdb_schema *schema;
70 };
71
72 static int acl_module_init(struct ldb_module *module)
73 {
74         struct ldb_context *ldb;
75         struct acl_private *data;
76         int ret;
77
78         ldb = ldb_module_get_ctx(module);
79
80         data = talloc_zero(module, struct acl_private);
81         if (data == NULL) {
82                 return ldb_oom(ldb);
83         }
84
85         data->acl_search = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"),
86                                         NULL, "acl", "search", true);
87         ldb_module_set_private(module, data);
88
89         ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
90         if (ret != LDB_SUCCESS) {
91                 ldb_debug(ldb, LDB_DEBUG_ERROR,
92                           "acl_module_init: Unable to register control with rootdse!\n");
93                 return ldb_operr(ldb);
94         }
95
96         return ldb_next_init(module);
97 }
98
99 static int acl_allowedAttributes(struct ldb_module *module,
100                                  const struct dsdb_schema *schema,
101                                  struct ldb_message *sd_msg,
102                                  struct ldb_message *msg,
103                                  struct acl_context *ac)
104 {
105         struct ldb_message_element *oc_el;
106         struct ldb_context *ldb = ldb_module_get_ctx(module);
107         TALLOC_CTX *mem_ctx;
108         const char **attr_list;
109         int i, ret;
110         const struct dsdb_class *objectclass;
111
112         /* If we don't have a schema yet, we can't do anything... */
113         if (schema == NULL) {
114                 ldb_asprintf_errstring(ldb, "cannot add allowedAttributes to %s because no schema is loaded", ldb_dn_get_linearized(msg->dn));
115                 return LDB_ERR_OPERATIONS_ERROR;
116         }
117
118         /* Must remove any existing attribute */
119         if (ac->allowedAttributes) {
120                 ldb_msg_remove_attr(msg, "allowedAttributes");
121         }
122
123         mem_ctx = talloc_new(msg);
124         if (!mem_ctx) {
125                 return ldb_oom(ldb);
126         }
127
128         oc_el = ldb_msg_find_element(sd_msg, "objectClass");
129         attr_list = dsdb_full_attribute_list(mem_ctx, schema, oc_el, DSDB_SCHEMA_ALL);
130         if (!attr_list) {
131                 ldb_asprintf_errstring(ldb, "acl: Failed to get list of attributes");
132                 talloc_free(mem_ctx);
133                 return LDB_ERR_OPERATIONS_ERROR;
134         }
135
136         /*
137          * Get the top-most structural object class for the ACL check
138          */
139         objectclass = dsdb_get_last_structural_class(ac->schema,
140                                                      oc_el);
141         if (objectclass == NULL) {
142                 ldb_asprintf_errstring(ldb, "acl_read: Failed to find a structural class for %s",
143                                        ldb_dn_get_linearized(sd_msg->dn));
144                 talloc_free(mem_ctx);
145                 return LDB_ERR_OPERATIONS_ERROR;
146         }
147
148         if (ac->allowedAttributes) {
149                 for (i=0; attr_list && attr_list[i]; i++) {
150                         ldb_msg_add_string(msg, "allowedAttributes", attr_list[i]);
151                 }
152         }
153         if (ac->allowedAttributesEffective) {
154                 struct security_descriptor *sd;
155                 struct dom_sid *sid = NULL;
156                 struct ldb_control *as_system = ldb_request_get_control(ac->req,
157                                                                         LDB_CONTROL_AS_SYSTEM_OID);
158
159                 if (as_system != NULL) {
160                         as_system->critical = 0;
161                 }
162
163                 ldb_msg_remove_attr(msg, "allowedAttributesEffective");
164                 if (ac->am_system || as_system) {
165                         for (i=0; attr_list && attr_list[i]; i++) {
166                                 ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
167                         }
168                         return LDB_SUCCESS;
169                 }
170
171                 ret = dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(module), mem_ctx, sd_msg, &sd);
172
173                 if (ret != LDB_SUCCESS) {
174                         return ret;
175                 }
176
177                 sid = samdb_result_dom_sid(mem_ctx, sd_msg, "objectSid");
178                 for (i=0; attr_list && attr_list[i]; i++) {
179                         const struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
180                                                                                         attr_list[i]);
181                         if (!attr) {
182                                 return ldb_operr(ldb);
183                         }
184                         /* remove constructed attributes */
185                         if (attr->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED
186                             || attr->systemOnly
187                             || (attr->linkID != 0 && attr->linkID % 2 != 0 )) {
188                                 continue;
189                         }
190                         ret = acl_check_access_on_attribute(module,
191                                                             msg,
192                                                             sd,
193                                                             sid,
194                                                             SEC_ADS_WRITE_PROP,
195                                                             attr,
196                                                             objectclass);
197                         if (ret == LDB_SUCCESS) {
198                                 ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
199                         }
200                 }
201         }
202         return LDB_SUCCESS;
203 }
204
205 static int acl_childClasses(struct ldb_module *module,
206                             const struct dsdb_schema *schema,
207                             struct ldb_message *sd_msg,
208                             struct ldb_message *msg,
209                             const char *attrName)
210 {
211         struct ldb_message_element *oc_el;
212         struct ldb_message_element *allowedClasses;
213         const struct dsdb_class *sclass;
214         unsigned int i, j;
215         int ret;
216
217         /* If we don't have a schema yet, we can't do anything... */
218         if (schema == NULL) {
219                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "cannot add childClassesEffective to %s because no schema is loaded", ldb_dn_get_linearized(msg->dn));
220                 return LDB_ERR_OPERATIONS_ERROR;
221         }
222
223         /* Must remove any existing attribute, or else confusion reigns */
224         ldb_msg_remove_attr(msg, attrName);
225         ret = ldb_msg_add_empty(msg, attrName, 0, &allowedClasses);
226         if (ret != LDB_SUCCESS) {
227                 return ret;
228         }
229
230         oc_el = ldb_msg_find_element(sd_msg, "objectClass");
231
232         for (i=0; oc_el && i < oc_el->num_values; i++) {
233                 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
234                 if (!sclass) {
235                         /* We don't know this class?  what is going on? */
236                         continue;
237                 }
238
239                 for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) {
240                         ldb_msg_add_string(msg, attrName, sclass->possibleInferiors[j]);
241                 }
242         }
243         if (allowedClasses->num_values > 1) {
244                 TYPESAFE_QSORT(allowedClasses->values, allowedClasses->num_values, data_blob_cmp);
245                 for (i=1 ; i < allowedClasses->num_values; i++) {
246                         struct ldb_val *val1 = &allowedClasses->values[i-1];
247                         struct ldb_val *val2 = &allowedClasses->values[i];
248                         if (data_blob_cmp(val1, val2) == 0) {
249                                 memmove(val1, val2, (allowedClasses->num_values - i) * sizeof(struct ldb_val));
250                                 allowedClasses->num_values--;
251                                 i--;
252                         }
253                 }
254         }
255
256         return LDB_SUCCESS;
257 }
258
259 static int acl_childClassesEffective(struct ldb_module *module,
260                                      const struct dsdb_schema *schema,
261                                      struct ldb_message *sd_msg,
262                                      struct ldb_message *msg,
263                                      struct acl_context *ac)
264 {
265         struct ldb_message_element *oc_el;
266         struct ldb_message_element *allowedClasses = NULL;
267         const struct dsdb_class *sclass;
268         struct security_descriptor *sd;
269         struct ldb_control *as_system = ldb_request_get_control(ac->req,
270                                                                 LDB_CONTROL_AS_SYSTEM_OID);
271         struct dom_sid *sid = NULL;
272         unsigned int i, j;
273         int ret;
274
275         if (as_system != NULL) {
276                 as_system->critical = 0;
277         }
278
279         if (ac->am_system || as_system) {
280                 return acl_childClasses(module, schema, sd_msg, msg, "allowedChildClassesEffective");
281         }
282
283         /* If we don't have a schema yet, we can't do anything... */
284         if (schema == NULL) {
285                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "cannot add allowedChildClassesEffective to %s because no schema is loaded", ldb_dn_get_linearized(msg->dn));
286                 return LDB_ERR_OPERATIONS_ERROR;
287         }
288
289         /* Must remove any existing attribute, or else confusion reigns */
290         ldb_msg_remove_attr(msg, "allowedChildClassesEffective");
291
292         oc_el = ldb_msg_find_element(sd_msg, "objectClass");
293         ret = dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(module), msg, sd_msg, &sd);
294         if (ret != LDB_SUCCESS) {
295                 return ret;
296         }
297
298         sid = samdb_result_dom_sid(msg, sd_msg, "objectSid");
299         for (i=0; oc_el && i < oc_el->num_values; i++) {
300                 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
301                 if (!sclass) {
302                         /* We don't know this class?  what is going on? */
303                         continue;
304                 }
305
306                 for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) {
307                         const struct dsdb_class *sc;
308
309                         sc = dsdb_class_by_lDAPDisplayName(schema,
310                                                            sclass->possibleInferiors[j]);
311                         if (!sc) {
312                                 /* We don't know this class?  what is going on? */
313                                 continue;
314                         }
315
316                         ret = acl_check_access_on_objectclass(module, ac,
317                                                               sd, sid,
318                                                               SEC_ADS_CREATE_CHILD,
319                                                               sc);
320                         if (ret == LDB_SUCCESS) {
321                                 ldb_msg_add_string(msg, "allowedChildClassesEffective",
322                                                    sclass->possibleInferiors[j]);
323                         }
324                 }
325         }
326         allowedClasses = ldb_msg_find_element(msg, "allowedChildClassesEffective");
327         if (!allowedClasses) {
328                 return LDB_SUCCESS;
329         }
330
331         if (allowedClasses->num_values > 1) {
332                 TYPESAFE_QSORT(allowedClasses->values, allowedClasses->num_values, data_blob_cmp);
333                 for (i=1 ; i < allowedClasses->num_values; i++) {
334                         struct ldb_val *val1 = &allowedClasses->values[i-1];
335                         struct ldb_val *val2 = &allowedClasses->values[i];
336                         if (data_blob_cmp(val1, val2) == 0) {
337                                 memmove(val1, val2, (allowedClasses->num_values - i) * sizeof( struct ldb_val));
338                                 allowedClasses->num_values--;
339                                 i--;
340                         }
341                 }
342         }
343         return LDB_SUCCESS;
344 }
345
346 static int acl_sDRightsEffective(struct ldb_module *module,
347                                  struct ldb_message *sd_msg,
348                                  struct ldb_message *msg,
349                                  struct acl_context *ac)
350 {
351         struct ldb_context *ldb = ldb_module_get_ctx(module);
352         struct ldb_message_element *rightsEffective;
353         int ret;
354         struct security_descriptor *sd;
355         struct ldb_control *as_system = ldb_request_get_control(ac->req,
356                                                                 LDB_CONTROL_AS_SYSTEM_OID);
357         struct dom_sid *sid = NULL;
358         uint32_t flags = 0;
359
360         if (as_system != NULL) {
361                 as_system->critical = 0;
362         }
363
364         /* Must remove any existing attribute, or else confusion reigns */
365         ldb_msg_remove_attr(msg, "sDRightsEffective");
366         ret = ldb_msg_add_empty(msg, "sDRightsEffective", 0, &rightsEffective);
367         if (ret != LDB_SUCCESS) {
368                 return ret;
369         }
370         if (ac->am_system || as_system) {
371                 flags = SECINFO_OWNER | SECINFO_GROUP |  SECINFO_SACL |  SECINFO_DACL;
372         } else {
373                 const struct dsdb_class *objectclass;
374                 const struct dsdb_attribute *attr;
375
376                 objectclass = dsdb_get_structural_oc_from_msg(ac->schema, sd_msg);
377                 if (objectclass == NULL) {
378                         return ldb_operr(ldb);
379                 }
380
381                 attr = dsdb_attribute_by_lDAPDisplayName(ac->schema,
382                                                          "nTSecurityDescriptor");
383                 if (attr == NULL) {
384                         return ldb_operr(ldb);
385                 }
386
387                 /* Get the security descriptor from the message */
388                 ret = dsdb_get_sd_from_ldb_message(ldb, msg, sd_msg, &sd);
389                 if (ret != LDB_SUCCESS) {
390                         return ret;
391                 }
392                 sid = samdb_result_dom_sid(msg, sd_msg, "objectSid");
393                 ret = acl_check_access_on_attribute(module,
394                                                     msg,
395                                                     sd,
396                                                     sid,
397                                                     SEC_STD_WRITE_OWNER,
398                                                     attr,
399                                                     objectclass);
400                 if (ret == LDB_SUCCESS) {
401                         flags |= SECINFO_OWNER | SECINFO_GROUP;
402                 }
403
404                 /*
405                  * This call is made with
406                  * IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS
407                  * and without reference to the dSHeuristics via
408                  * dsdb_block_owner_implicit_rights().  This is
409                  * probably a Windows bug but for now we match
410                  * exactly.
411                  */
412                 ret = acl_check_access_on_attribute_implicit_owner(
413                         module,
414                         msg,
415                         sd,
416                         sid,
417                         SEC_STD_WRITE_DAC,
418                         attr,
419                         objectclass,
420                         IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS);
421                 if (ret == LDB_SUCCESS) {
422                         flags |= SECINFO_DACL;
423                 }
424                 ret = acl_check_access_on_attribute(module,
425                                                     msg,
426                                                     sd,
427                                                     sid,
428                                                     SEC_FLAG_SYSTEM_SECURITY,
429                                                     attr,
430                                                     objectclass);
431                 if (ret == LDB_SUCCESS) {
432                         flags |= SECINFO_SACL;
433                 }
434         }
435
436         if (flags != (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL)) {
437                 const struct ldb_message_element *el = samdb_find_attribute(ldb,
438                                                                             sd_msg,
439                                                                             "objectclass",
440                                                                             "computer");
441                 if (el != NULL) {
442                         return LDB_SUCCESS;
443                 }
444         }
445
446         return samdb_msg_add_uint(ldb_module_get_ctx(module), msg, msg,
447                                   "sDRightsEffective", flags);
448 }
449
450 static int acl_validate_spn_value(TALLOC_CTX *mem_ctx,
451                                   struct ldb_context *ldb,
452                                   const struct ldb_val *spn_value,
453                                   uint32_t userAccountControl,
454                                   const struct ldb_val *samAccountName,
455                                   const struct ldb_val *dnsHostName,
456                                   const char *netbios_name,
457                                   const char *ntds_guid)
458 {
459         krb5_error_code ret, princ_size;
460         krb5_context krb_ctx;
461         krb5_error_code kerr;
462         krb5_principal principal;
463         char *instanceName = NULL;
464         char *serviceType = NULL;
465         char *serviceName = NULL;
466         const char *spn_value_str = NULL;
467         size_t account_name_len;
468         const char *forest_name = samdb_forest_name(ldb, mem_ctx);
469         const char *base_domain = samdb_default_domain_name(ldb, mem_ctx);
470         struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
471                                                           struct loadparm_context);
472         bool is_dc = (userAccountControl & UF_SERVER_TRUST_ACCOUNT) ||
473                 (userAccountControl & UF_PARTIAL_SECRETS_ACCOUNT);
474
475         spn_value_str = talloc_strndup(mem_ctx,
476                                        (const char *)spn_value->data,
477                                        spn_value->length);
478         if (spn_value_str == NULL) {
479                 return ldb_oom(ldb);
480         }
481
482         if (spn_value->length == samAccountName->length &&
483             strncasecmp((const char *)spn_value->data,
484                         (const char *)samAccountName->data,
485                         spn_value->length) == 0)
486         {
487                 /* MacOS X sets this value, and setting an SPN of your
488                  * own samAccountName is both pointless and safe */
489                 return LDB_SUCCESS;
490         }
491
492         kerr = smb_krb5_init_context_basic(mem_ctx,
493                                            lp_ctx,
494                                            &krb_ctx);
495         if (kerr != 0) {
496                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
497                                  "Could not initialize kerberos context.");
498         }
499
500         ret = krb5_parse_name(krb_ctx, spn_value_str, &principal);
501         if (ret) {
502                 krb5_free_context(krb_ctx);
503                 return LDB_ERR_CONSTRAINT_VIOLATION;
504         }
505
506         princ_size = krb5_princ_size(krb_ctx, principal);
507         if (princ_size < 2) {
508                 DBG_WARNING("princ_size=%d\n", princ_size);
509                 goto fail;
510         }
511
512         ret = smb_krb5_principal_get_comp_string(mem_ctx, krb_ctx,
513                                                           principal, 1, &instanceName);
514         if (ret) {
515                 goto fail;
516         }
517         ret = smb_krb5_principal_get_comp_string(mem_ctx, krb_ctx,
518                                                  principal, 0, &serviceType);
519         if (ret) {
520                 goto fail;
521         }
522         if (krb5_princ_size(krb_ctx, principal) == 3) {
523                 ret = smb_krb5_principal_get_comp_string(mem_ctx, krb_ctx,
524                                                          principal, 2, &serviceName);
525                 if (ret) {
526                         goto fail;
527                 }
528         }
529
530         if (serviceName) {
531                 if (!is_dc) {
532                         DBG_WARNING("is_dc=false, serviceName=%s,"
533                                     "serviceType=%s\n", serviceName,
534                                   serviceType);
535                         goto fail;
536                 }
537                 if (strcasecmp(serviceType, "ldap") == 0) {
538                         if (strcasecmp(serviceName, netbios_name) != 0 &&
539                             strcasecmp(serviceName, forest_name) != 0) {
540                                 DBG_WARNING("serviceName=%s\n", serviceName);
541                                 goto fail;
542                         }
543
544                 } else if (strcasecmp(serviceType, "gc") == 0) {
545                         if (strcasecmp(serviceName, forest_name) != 0) {
546                                 DBG_WARNING("serviceName=%s\n", serviceName);
547                                 goto fail;
548                         }
549                 } else {
550                         if (strcasecmp(serviceName, base_domain) != 0 &&
551                             strcasecmp(serviceName, netbios_name) != 0) {
552                                 DBG_WARNING("serviceType=%s, "
553                                             "serviceName=%s\n",
554                                             serviceType, serviceName);
555                                 goto fail;
556                         }
557                 }
558         }
559
560         account_name_len = samAccountName->length;
561         if (account_name_len &&
562             samAccountName->data[account_name_len - 1] == '$')
563         {
564                 /* Account for the '$' character. */
565                 --account_name_len;
566         }
567
568         /* instanceName can be samAccountName without $ or dnsHostName
569          * or "ntds_guid._msdcs.forest_domain for DC objects */
570         if (strlen(instanceName) == account_name_len
571             && strncasecmp(instanceName,
572                            (const char *)samAccountName->data,
573                            account_name_len) == 0)
574         {
575                 goto success;
576         }
577         if ((dnsHostName != NULL) &&
578             strlen(instanceName) == dnsHostName->length &&
579             (strncasecmp(instanceName,
580                          (const char *)dnsHostName->data,
581                          dnsHostName->length) == 0))
582         {
583                 goto success;
584         }
585         if (is_dc) {
586                 const char *guid_str = NULL;
587                 guid_str = talloc_asprintf(mem_ctx,"%s._msdcs.%s",
588                                            ntds_guid,
589                                            forest_name);
590                 if (strcasecmp(instanceName, guid_str) == 0) {
591                         goto success;
592                 }
593         }
594
595 fail:
596         krb5_free_principal(krb_ctx, principal);
597         krb5_free_context(krb_ctx);
598         ldb_debug_set(ldb, LDB_DEBUG_WARNING,
599                       "acl: spn validation failed for "
600                       "spn[%.*s] uac[0x%x] account[%.*s] hostname[%.*s] "
601                       "nbname[%s] ntds[%s] forest[%s] domain[%s]\n",
602                       (int)spn_value->length, spn_value->data,
603                       (unsigned)userAccountControl,
604                       (int)samAccountName->length, samAccountName->data,
605                       dnsHostName != NULL ? (int)dnsHostName->length : 0,
606                       dnsHostName != NULL ? (const char *)dnsHostName->data : "",
607                       netbios_name, ntds_guid,
608                       forest_name, base_domain);
609         return LDB_ERR_CONSTRAINT_VIOLATION;
610
611 success:
612         krb5_free_principal(krb_ctx, principal);
613         krb5_free_context(krb_ctx);
614         return LDB_SUCCESS;
615 }
616
617 /*
618  * Passing in 'el' is critical, we want to check all the values.
619  *
620  */
621 static int acl_check_spn(TALLOC_CTX *mem_ctx,
622                          struct ldb_module *module,
623                          struct ldb_request *req,
624                          const struct ldb_message_element *el,
625                          struct security_descriptor *sd,
626                          struct dom_sid *sid,
627                          const struct dsdb_attribute *attr,
628                          const struct dsdb_class *objectclass,
629                          const struct ldb_control *implicit_validated_write_control)
630 {
631         int ret;
632         unsigned int i;
633         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
634         struct ldb_context *ldb = ldb_module_get_ctx(module);
635         struct ldb_result *acl_res;
636         struct ldb_result *netbios_res;
637         struct ldb_dn *partitions_dn = samdb_partitions_dn(ldb, tmp_ctx);
638         uint32_t userAccountControl;
639         const char *netbios_name;
640         const struct ldb_val *dns_host_name_val = NULL;
641         const struct ldb_val *sam_account_name_val = NULL;
642         struct GUID ntds;
643         char *ntds_guid = NULL;
644         const struct ldb_message *msg = NULL;
645         const struct ldb_message *search_res = NULL;
646
647         static const char *acl_attrs[] = {
648                 "samAccountName",
649                 "dnsHostName",
650                 "userAccountControl",
651                 NULL
652         };
653         static const char *netbios_attrs[] = {
654                 "nETBIOSName",
655                 NULL
656         };
657
658         if (req->operation == LDB_MODIFY) {
659                 msg = req->op.mod.message;
660         } else if (req->operation == LDB_ADD) {
661                 msg = req->op.add.message;
662         }
663
664         if (implicit_validated_write_control != NULL) {
665                 /*
666                  * The validated write control dispenses with ACL
667                  * checks. We act as if we have an implicit Self Write
668                  * privilege, but, assuming we don't have Write
669                  * Property, still proceed with further validation
670                  * checks.
671                  */
672         } else {
673                 /* if we have wp, we can do whatever we like */
674                 if (acl_check_access_on_attribute(module,
675                                                   tmp_ctx,
676                                                   sd,
677                                                   sid,
678                                                   SEC_ADS_WRITE_PROP,
679                                                   attr, objectclass) == LDB_SUCCESS) {
680                         talloc_free(tmp_ctx);
681                         return LDB_SUCCESS;
682                 }
683
684                 ret = acl_check_extended_right(tmp_ctx,
685                                                module,
686                                                req,
687                                                objectclass,
688                                                sd,
689                                                acl_user_token(module),
690                                                GUID_DRS_VALIDATE_SPN,
691                                                SEC_ADS_SELF_WRITE,
692                                                sid);
693
694                 if (ret != LDB_SUCCESS) {
695                         dsdb_acl_debug(sd, acl_user_token(module),
696                                        msg->dn,
697                                        true,
698                                        10);
699                         talloc_free(tmp_ctx);
700                         return ret;
701                 }
702         }
703
704         /*
705          * If we have "validated write spn", allow delete of any
706          * existing value (this keeps constrained delete to the same
707          * rules as unconstrained)
708          */
709         if (req->operation == LDB_MODIFY) {
710                 /*
711                  * If not add or replace (eg delete),
712                  * return success
713                  */
714                 if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD &&
715                     LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE)
716                 {
717                         talloc_free(tmp_ctx);
718                         return LDB_SUCCESS;
719                 }
720
721                 ret = dsdb_module_search_dn(module, tmp_ctx,
722                                             &acl_res, msg->dn,
723                                             acl_attrs,
724                                             DSDB_FLAG_NEXT_MODULE |
725                                             DSDB_FLAG_AS_SYSTEM |
726                                             DSDB_SEARCH_SHOW_RECYCLED,
727                                             req);
728                 if (ret != LDB_SUCCESS) {
729                         talloc_free(tmp_ctx);
730                         return ret;
731                 }
732
733                 search_res = acl_res->msgs[0];
734         } else if (req->operation == LDB_ADD) {
735                 search_res = msg;
736         } else {
737                 talloc_free(tmp_ctx);
738                 return LDB_ERR_OPERATIONS_ERROR;
739         }
740
741         if (req->operation == LDB_MODIFY) {
742                 dns_host_name_val = ldb_msg_find_ldb_val(search_res, "dNSHostName");
743         }
744
745         ret = dsdb_msg_get_single_value(msg,
746                                         "dNSHostName",
747                                         dns_host_name_val,
748                                         &dns_host_name_val,
749                                         req->operation);
750         if (ret != LDB_SUCCESS) {
751                 talloc_free(tmp_ctx);
752                 return ret;
753         }
754
755         userAccountControl = ldb_msg_find_attr_as_uint(search_res, "userAccountControl", 0);
756
757         if (req->operation == LDB_MODIFY) {
758                 sam_account_name_val = ldb_msg_find_ldb_val(search_res, "sAMAccountName");
759         }
760
761         ret = dsdb_msg_get_single_value(msg,
762                                         "sAMAccountName",
763                                         sam_account_name_val,
764                                         &sam_account_name_val,
765                                         req->operation);
766         if (ret != LDB_SUCCESS) {
767                 talloc_free(tmp_ctx);
768                 return ret;
769         }
770
771         ret = dsdb_module_search(module, tmp_ctx,
772                                  &netbios_res, partitions_dn,
773                                  LDB_SCOPE_ONELEVEL,
774                                  netbios_attrs,
775                                  DSDB_FLAG_NEXT_MODULE |
776                                  DSDB_FLAG_AS_SYSTEM,
777                                  req,
778                                  "(ncName=%s)",
779                                  ldb_dn_get_linearized(ldb_get_default_basedn(ldb)));
780
781         netbios_name = ldb_msg_find_attr_as_string(netbios_res->msgs[0], "nETBIOSName", NULL);
782
783         /*
784          * NTDSDSA objectGuid of object we are checking SPN for
785          *
786          * Note - do we have the necessary attributes for this during an add operation?
787          * How should we test this?
788          */
789         if (userAccountControl & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
790                 ret = dsdb_module_find_ntdsguid_for_computer(module, tmp_ctx,
791                                                              msg->dn, &ntds, req);
792                 if (ret != LDB_SUCCESS) {
793                         ldb_asprintf_errstring(ldb, "Failed to find NTDSDSA objectGuid for %s: %s",
794                                                ldb_dn_get_linearized(msg->dn),
795                                                ldb_strerror(ret));
796                         talloc_free(tmp_ctx);
797                         return LDB_ERR_OPERATIONS_ERROR;
798                 }
799                 ntds_guid = GUID_string(tmp_ctx, &ntds);
800         }
801
802         for (i=0; i < el->num_values; i++) {
803                 ret = acl_validate_spn_value(tmp_ctx,
804                                              ldb,
805                                              &el->values[i],
806                                              userAccountControl,
807                                              sam_account_name_val,
808                                              dns_host_name_val,
809                                              netbios_name,
810                                              ntds_guid);
811                 if (ret != LDB_SUCCESS) {
812                         talloc_free(tmp_ctx);
813                         return ret;
814                 }
815         }
816         talloc_free(tmp_ctx);
817         return LDB_SUCCESS;
818 }
819
820 static int acl_check_dns_host_name(TALLOC_CTX *mem_ctx,
821                                    struct ldb_module *module,
822                                    struct ldb_request *req,
823                                    const struct ldb_message_element *el,
824                                    struct security_descriptor *sd,
825                                    struct dom_sid *sid,
826                                    const struct dsdb_attribute *attr,
827                                    const struct dsdb_class *objectclass,
828                                    const struct ldb_control *implicit_validated_write_control)
829 {
830         int ret;
831         unsigned i;
832         TALLOC_CTX *tmp_ctx = NULL;
833         struct ldb_context *ldb = ldb_module_get_ctx(module);
834         const struct dsdb_schema *schema = NULL;
835         const struct ldb_message_element *allowed_suffixes = NULL;
836         struct ldb_result *nc_res = NULL;
837         struct ldb_dn *nc_root = NULL;
838         const char *nc_dns_name = NULL;
839         const char *dnsHostName_str = NULL;
840         size_t dns_host_name_len;
841         size_t account_name_len;
842         const struct ldb_message *msg = NULL;
843         const struct ldb_message *search_res = NULL;
844         const struct ldb_val *samAccountName = NULL;
845         const struct ldb_val *dnsHostName = NULL;
846         const struct dsdb_class *computer_objectclass = NULL;
847         bool is_subclass;
848
849         static const char *nc_attrs[] = {
850                 "msDS-AllowedDNSSuffixes",
851                 NULL
852         };
853
854         tmp_ctx = talloc_new(mem_ctx);
855         if (tmp_ctx == NULL) {
856                 return ldb_oom(ldb);
857         }
858
859         if (req->operation == LDB_MODIFY) {
860                 msg = req->op.mod.message;
861         } else if (req->operation == LDB_ADD) {
862                 msg = req->op.add.message;
863         }
864
865         if (implicit_validated_write_control != NULL) {
866                 /*
867                  * The validated write control dispenses with ACL
868                  * checks. We act as if we have an implicit Self Write
869                  * privilege, but, assuming we don't have Write
870                  * Property, still proceed with further validation
871                  * checks.
872                  */
873         } else {
874                 /* if we have wp, we can do whatever we like */
875                 ret = acl_check_access_on_attribute(module,
876                                                     tmp_ctx,
877                                                     sd,
878                                                     sid,
879                                                     SEC_ADS_WRITE_PROP,
880                                                     attr, objectclass);
881                 if (ret == LDB_SUCCESS) {
882                         talloc_free(tmp_ctx);
883                         return LDB_SUCCESS;
884                 }
885
886                 ret = acl_check_extended_right(tmp_ctx,
887                                                module,
888                                                req,
889                                                objectclass,
890                                                sd,
891                                                acl_user_token(module),
892                                                GUID_DRS_DNS_HOST_NAME,
893                                                SEC_ADS_SELF_WRITE,
894                                                sid);
895
896                 if (ret != LDB_SUCCESS) {
897                         dsdb_acl_debug(sd, acl_user_token(module),
898                                        msg->dn,
899                                        true,
900                                        10);
901                         talloc_free(tmp_ctx);
902                         return ret;
903                 }
904         }
905
906         /*
907          * If we have "validated write dnshostname", allow delete of
908          * any existing value (this keeps constrained delete to the
909          * same rules as unconstrained)
910          */
911         if (req->operation == LDB_MODIFY) {
912                 struct ldb_result *acl_res = NULL;
913
914                 static const char *acl_attrs[] = {
915                         "sAMAccountName",
916                         NULL
917                 };
918
919                 /*
920                  * If not add or replace (eg delete),
921                  * return success
922                  */
923                 if ((el->flags
924                      & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0)
925                 {
926                         talloc_free(tmp_ctx);
927                         return LDB_SUCCESS;
928                 }
929
930                 ret = dsdb_module_search_dn(module, tmp_ctx,
931                                             &acl_res, msg->dn,
932                                             acl_attrs,
933                                             DSDB_FLAG_NEXT_MODULE |
934                                             DSDB_FLAG_AS_SYSTEM |
935                                             DSDB_SEARCH_SHOW_RECYCLED,
936                                             req);
937                 if (ret != LDB_SUCCESS) {
938                         talloc_free(tmp_ctx);
939                         return ret;
940                 }
941
942                 search_res = acl_res->msgs[0];
943         } else if (req->operation == LDB_ADD) {
944                 search_res = msg;
945         } else {
946                 talloc_free(tmp_ctx);
947                 return LDB_ERR_OPERATIONS_ERROR;
948         }
949
950         /* Check if the account has objectclass 'computer' or 'server'. */
951
952         schema = dsdb_get_schema(ldb, req);
953         if (schema == NULL) {
954                 talloc_free(tmp_ctx);
955                 return ldb_operr(ldb);
956         }
957
958         computer_objectclass = dsdb_class_by_lDAPDisplayName(schema, "computer");
959         if (computer_objectclass == NULL) {
960                 talloc_free(tmp_ctx);
961                 return ldb_operr(ldb);
962         }
963
964         is_subclass = dsdb_is_subclass_of(schema, objectclass, computer_objectclass);
965         if (!is_subclass) {
966                 /* The account is not a computer -- check if it's a server. */
967
968                 const struct dsdb_class *server_objectclass = NULL;
969
970                 server_objectclass = dsdb_class_by_lDAPDisplayName(schema, "server");
971                 if (server_objectclass == NULL) {
972                         talloc_free(tmp_ctx);
973                         return ldb_operr(ldb);
974                 }
975
976                 is_subclass = dsdb_is_subclass_of(schema, objectclass, server_objectclass);
977                 if (!is_subclass) {
978                         /* Not a computer or server, so no need to validate. */
979                         talloc_free(tmp_ctx);
980                         return LDB_SUCCESS;
981                 }
982         }
983
984         if (req->operation == LDB_MODIFY) {
985                 samAccountName = ldb_msg_find_ldb_val(search_res, "sAMAccountName");
986         }
987
988         ret = dsdb_msg_get_single_value(msg,
989                                         "sAMAccountName",
990                                         samAccountName,
991                                         &samAccountName,
992                                         req->operation);
993         if (ret != LDB_SUCCESS) {
994                 talloc_free(tmp_ctx);
995                 return ret;
996         }
997
998         account_name_len = samAccountName->length;
999         if (account_name_len && samAccountName->data[account_name_len - 1] == '$') {
1000                 /* Account for the '$' character. */
1001                 --account_name_len;
1002         }
1003
1004         /* Check for add or replace requests with no value. */
1005         if (el->num_values == 0) {
1006                 talloc_free(tmp_ctx);
1007                 return ldb_operr(ldb);
1008         }
1009         dnsHostName = &el->values[0];
1010
1011         dnsHostName_str = (const char *)dnsHostName->data;
1012         dns_host_name_len = dnsHostName->length;
1013
1014         /* Check that sAMAccountName matches the new dNSHostName. */
1015
1016         if (dns_host_name_len < account_name_len) {
1017                 goto fail;
1018         }
1019         if (strncasecmp(dnsHostName_str,
1020                         (const char *)samAccountName->data,
1021                         account_name_len) != 0)
1022         {
1023                 goto fail;
1024         }
1025
1026         dnsHostName_str += account_name_len;
1027         dns_host_name_len -= account_name_len;
1028
1029         /* Check the '.' character */
1030
1031         if (dns_host_name_len == 0 || *dnsHostName_str != '.') {
1032                 goto fail;
1033         }
1034
1035         ++dnsHostName_str;
1036         --dns_host_name_len;
1037
1038         /* Now we check the suffix. */
1039
1040         ret = dsdb_find_nc_root(ldb,
1041                                 tmp_ctx,
1042                                 search_res->dn,
1043                                 &nc_root);
1044         if (ret != LDB_SUCCESS) {
1045                 talloc_free(tmp_ctx);
1046                 return ret;
1047         }
1048
1049         nc_dns_name = samdb_dn_to_dns_domain(tmp_ctx, nc_root);
1050         if (nc_dns_name == NULL) {
1051                 talloc_free(tmp_ctx);
1052                 return ldb_operr(ldb);
1053         }
1054
1055         if (strlen(nc_dns_name) == dns_host_name_len &&
1056             strncasecmp(dnsHostName_str,
1057                         nc_dns_name,
1058                         dns_host_name_len) == 0)
1059         {
1060                 /* It matches -- success. */
1061                 talloc_free(tmp_ctx);
1062                 return LDB_SUCCESS;
1063         }
1064
1065         /* We didn't get a match, so now try msDS-AllowedDNSSuffixes. */
1066
1067         ret = dsdb_module_search_dn(module, tmp_ctx,
1068                                     &nc_res, nc_root,
1069                                     nc_attrs,
1070                                     DSDB_FLAG_NEXT_MODULE |
1071                                     DSDB_FLAG_AS_SYSTEM |
1072                                     DSDB_SEARCH_SHOW_RECYCLED,
1073                                     req);
1074         if (ret != LDB_SUCCESS) {
1075                 talloc_free(tmp_ctx);
1076                 return ret;
1077         }
1078
1079         allowed_suffixes = ldb_msg_find_element(nc_res->msgs[0],
1080                                                 "msDS-AllowedDNSSuffixes");
1081         if (allowed_suffixes == NULL) {
1082                 goto fail;
1083         }
1084
1085         for (i = 0; i < allowed_suffixes->num_values; ++i) {
1086                 const struct ldb_val *suffix = &allowed_suffixes->values[i];
1087
1088                 if (suffix->length == dns_host_name_len &&
1089                     strncasecmp(dnsHostName_str,
1090                                 (const char *)suffix->data,
1091                                 dns_host_name_len) == 0)
1092                 {
1093                         /* It matches -- success. */
1094                         talloc_free(tmp_ctx);
1095                         return LDB_SUCCESS;
1096                 }
1097         }
1098
1099 fail:
1100         ldb_debug_set(ldb, LDB_DEBUG_WARNING,
1101                       "acl: hostname validation failed for "
1102                       "hostname[%.*s] account[%.*s]\n",
1103                       (int)dnsHostName->length, dnsHostName->data,
1104                       (int)samAccountName->length, samAccountName->data);
1105         talloc_free(tmp_ctx);
1106         return LDB_ERR_CONSTRAINT_VIOLATION;
1107 }
1108
1109 /* checks if modifications are allowed on "Member" attribute */
1110 static int acl_check_self_membership(TALLOC_CTX *mem_ctx,
1111                                      struct ldb_module *module,
1112                                      struct ldb_request *req,
1113                                      struct security_descriptor *sd,
1114                                      struct dom_sid *sid,
1115                                      const struct dsdb_attribute *attr,
1116                                      const struct dsdb_class *objectclass)
1117 {
1118         int ret;
1119         unsigned int i;
1120         struct ldb_context *ldb = ldb_module_get_ctx(module);
1121         struct ldb_dn *user_dn;
1122         struct ldb_message_element *member_el;
1123         const struct ldb_message *msg = NULL;
1124
1125         if (req->operation == LDB_MODIFY) {
1126                 msg = req->op.mod.message;
1127         } else if (req->operation == LDB_ADD) {
1128                 msg = req->op.add.message;
1129         } else {
1130                 return LDB_ERR_OPERATIONS_ERROR;
1131         }
1132
1133         /* if we have wp, we can do whatever we like */
1134         if (acl_check_access_on_attribute(module,
1135                                           mem_ctx,
1136                                           sd,
1137                                           sid,
1138                                           SEC_ADS_WRITE_PROP,
1139                                           attr, objectclass) == LDB_SUCCESS) {
1140                 return LDB_SUCCESS;
1141         }
1142         /* if we are adding/deleting ourselves, check for self membership */
1143         ret = dsdb_find_dn_by_sid(ldb, mem_ctx,
1144                                   &acl_user_token(module)->sids[PRIMARY_USER_SID_INDEX],
1145                                   &user_dn);
1146         if (ret != LDB_SUCCESS) {
1147                 return ret;
1148         }
1149         member_el = ldb_msg_find_element(msg, "member");
1150         if (!member_el) {
1151                 return ldb_operr(ldb);
1152         }
1153         /* user can only remove oneself */
1154         if (member_el->num_values == 0) {
1155                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1156         }
1157         for (i = 0; i < member_el->num_values; i++) {
1158                 if (strcasecmp((const char *)member_el->values[i].data,
1159                                ldb_dn_get_extended_linearized(mem_ctx, user_dn, 1)) != 0) {
1160                         return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1161                 }
1162         }
1163         ret = acl_check_extended_right(mem_ctx,
1164                                        module,
1165                                        req,
1166                                        objectclass,
1167                                        sd,
1168                                        acl_user_token(module),
1169                                        GUID_DRS_SELF_MEMBERSHIP,
1170                                        SEC_ADS_SELF_WRITE,
1171                                        sid);
1172         if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1173                 dsdb_acl_debug(sd, acl_user_token(module),
1174                                msg->dn,
1175                                true,
1176                                10);
1177         }
1178         return ret;
1179 }
1180
1181 static int acl_add(struct ldb_module *module, struct ldb_request *req)
1182 {
1183         int ret;
1184         struct ldb_dn *parent;
1185         struct ldb_context *ldb;
1186         const struct dsdb_schema *schema;
1187         const struct dsdb_class *objectclass;
1188         const struct dsdb_class *computer_objectclass = NULL;
1189         const struct ldb_message_element *oc_el = NULL;
1190         struct ldb_message_element sorted_oc_el;
1191         struct ldb_control *sd_ctrl = NULL;
1192         struct ldb_message_element *el;
1193         unsigned int instanceType = 0;
1194         struct dsdb_control_calculated_default_sd *control_sd = NULL;
1195         const struct dsdb_attribute *attr = NULL;
1196         const char **must_contain = NULL;
1197         const struct ldb_message *msg = req->op.add.message;
1198         const struct dom_sid *domain_sid = NULL;
1199         int i = 0;
1200         bool attribute_authorization;
1201         bool is_subclass;
1202
1203         if (ldb_dn_is_special(msg->dn)) {
1204                 return ldb_next_request(module, req);
1205         }
1206
1207         if (dsdb_have_system_access(module, req, SYSTEM_CONTROL_STRIP_CRITICAL))
1208         {
1209                 return ldb_next_request(module, req);
1210         }
1211
1212         ldb = ldb_module_get_ctx(module);
1213         domain_sid = samdb_domain_sid(ldb);
1214
1215         parent = ldb_dn_get_parent(req, msg->dn);
1216         if (parent == NULL) {
1217                 return ldb_oom(ldb);
1218         }
1219
1220         schema = dsdb_get_schema(ldb, req);
1221         if (!schema) {
1222                 return ldb_operr(ldb);
1223         }
1224
1225         /* Find the objectclass of the new account. */
1226
1227         oc_el = ldb_msg_find_element(msg, "objectclass");
1228         if (oc_el == NULL) {
1229                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1230                                        "acl: unable to find or validate structural objectClass on %s\n",
1231                                        ldb_dn_get_linearized(msg->dn));
1232                 return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
1233         }
1234
1235         schema = dsdb_get_schema(ldb, req);
1236         if (schema == NULL) {
1237                 return ldb_operr(ldb);
1238         }
1239
1240         ret = dsdb_sort_objectClass_attr(ldb, schema, oc_el, req, &sorted_oc_el);
1241         if (ret != LDB_SUCCESS) {
1242                 return ret;
1243         }
1244
1245         objectclass = dsdb_get_last_structural_class(schema, &sorted_oc_el);
1246         if (objectclass == NULL) {
1247                 return ldb_operr(ldb);
1248         }
1249
1250         el = ldb_msg_find_element(msg, "instanceType");
1251         if ((el != NULL) && (el->num_values != 1)) {
1252                 ldb_set_errstring(ldb, "acl: the 'instanceType' attribute is single-valued!");
1253                 return LDB_ERR_UNWILLING_TO_PERFORM;
1254         }
1255
1256         instanceType = ldb_msg_find_attr_as_uint(msg,
1257                                                  "instanceType", 0);
1258         if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
1259                 static const char *no_attrs[] = { NULL };
1260                 struct ldb_result *partition_res;
1261                 struct ldb_dn *partitions_dn;
1262
1263                 partitions_dn = samdb_partitions_dn(ldb, req);
1264                 if (!partitions_dn) {
1265                         ldb_set_errstring(ldb, "acl: CN=partitions dn could not be generated!");
1266                         return LDB_ERR_UNWILLING_TO_PERFORM;
1267                 }
1268
1269                 ret = dsdb_module_search(module, req, &partition_res,
1270                                          partitions_dn, LDB_SCOPE_ONELEVEL,
1271                                          no_attrs,
1272                                          DSDB_FLAG_NEXT_MODULE |
1273                                          DSDB_FLAG_AS_SYSTEM |
1274                                          DSDB_SEARCH_ONE_ONLY |
1275                                          DSDB_SEARCH_SHOW_RECYCLED,
1276                                          req,
1277                                          "(&(nCName=%s)(objectClass=crossRef))",
1278                                          ldb_dn_get_linearized(msg->dn));
1279
1280                 if (ret == LDB_SUCCESS) {
1281                         /* Check that we can write to the crossRef object MS-ADTS 3.1.1.5.2.8.2 */
1282                         ret = dsdb_module_check_access_on_dn(module, req, partition_res->msgs[0]->dn,
1283                                                              SEC_ADS_WRITE_PROP,
1284                                                              &objectclass->schemaIDGUID, req);
1285                         if (ret != LDB_SUCCESS) {
1286                                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1287                                                        "acl: ACL check failed on crossRef object %s: %s\n",
1288                                                        ldb_dn_get_linearized(partition_res->msgs[0]->dn),
1289                                                        ldb_errstring(ldb));
1290                                 return ret;
1291                         }
1292
1293                         /*
1294                          * TODO: Remaining checks, like if we are
1295                          * the naming master etc need to be handled
1296                          * in the instanceType module
1297                          */
1298                         /* Note - do we need per-attribute checks? */
1299                         return ldb_next_request(module, req);
1300                 }
1301
1302                 /* Check that we can create a crossRef object MS-ADTS 3.1.1.5.2.8.2 */
1303                 ret = dsdb_module_check_access_on_dn(module, req, partitions_dn,
1304                                                      SEC_ADS_CREATE_CHILD,
1305                                                      &objectclass->schemaIDGUID, req);
1306                 if (ret == LDB_ERR_NO_SUCH_OBJECT &&
1307                     ldb_request_get_control(req, LDB_CONTROL_RELAX_OID))
1308                 {
1309                         /* Allow provision bootstrap */
1310                         ret = LDB_SUCCESS;
1311                 }
1312                 if (ret != LDB_SUCCESS) {
1313                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
1314                                                "acl: ACL check failed on CN=Partitions crossRef container %s: %s\n",
1315                                                ldb_dn_get_linearized(partitions_dn), ldb_errstring(ldb));
1316                         return ret;
1317                 }
1318
1319                 /*
1320                  * TODO: Remaining checks, like if we are the naming
1321                  * master and adding the crossRef object need to be
1322                  * handled in the instanceType module
1323                  */
1324         } else {
1325                 ret = dsdb_module_check_access_on_dn(module, req, parent,
1326                                                      SEC_ADS_CREATE_CHILD,
1327                                                      &objectclass->schemaIDGUID, req);
1328                 if (ret != LDB_SUCCESS) {
1329                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
1330                                                "acl: unable to get access to %s\n",
1331                                                ldb_dn_get_linearized(msg->dn));
1332                         return ret;
1333                 }
1334         }
1335
1336         attribute_authorization = dsdb_attribute_authz_on_ldap_add(module,
1337                                                                    req,
1338                                                                    req);
1339         if (!attribute_authorization) {
1340                 /* Skip the remaining checks */
1341                 goto success;
1342         }
1343
1344         /* Check if we have computer objectclass. */
1345         computer_objectclass = dsdb_class_by_lDAPDisplayName(schema, "computer");
1346         if (computer_objectclass == NULL) {
1347                 return ldb_operr(ldb);
1348         }
1349
1350         is_subclass = dsdb_is_subclass_of(schema, objectclass, computer_objectclass);
1351         if (!is_subclass) {
1352                 /*
1353                  * This object is not a computer (or derived from computer), so
1354                  * skip the remaining checks.
1355                  */
1356                 goto success;
1357         }
1358
1359         /*
1360          * we have established we have CC right, now check per-attribute
1361          * access based on the default SD
1362          */
1363
1364         sd_ctrl = ldb_request_get_control(req,
1365                                           DSDB_CONTROL_CALCULATED_DEFAULT_SD_OID);
1366         if (sd_ctrl == NULL) {
1367                 goto success;
1368         }
1369
1370         {
1371                 TALLOC_CTX *tmp_ctx = talloc_new(req);
1372                 control_sd = (struct dsdb_control_calculated_default_sd *) sd_ctrl->data;
1373                 DBG_DEBUG("Received cookie descriptor %s\n\n",
1374                           sddl_encode(tmp_ctx, control_sd->default_sd, domain_sid));
1375                 TALLOC_FREE(tmp_ctx);
1376                 /* Mark the "change" control as uncritical (done) */
1377                 sd_ctrl->critical = false;
1378         }
1379
1380         /*
1381          * At this point we do not yet have the object's SID, so we
1382          * leave it empty. It is irrelevant, as it is used to expand
1383          * Principal-Self, and rights granted to PS will have no effect
1384          * in this case
1385          */
1386         /* check if we have WD, no need to perform other attribute checks if we do */
1387         attr = dsdb_attribute_by_lDAPDisplayName(schema, "nTSecurityDescriptor");
1388         if (attr == NULL) {
1389                 return ldb_operr(ldb);
1390         }
1391
1392         if (control_sd->specified_sacl) {
1393                 const struct security_token *token = acl_user_token(module);
1394                 bool has_priv = security_token_has_privilege(token, SEC_PRIV_SECURITY);
1395                 if (!has_priv) {
1396                         return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1397                 }
1398         }
1399
1400         ret = acl_check_access_on_attribute(module,
1401                                             req,
1402                                             control_sd->default_sd,
1403                                             NULL,
1404                                             SEC_STD_WRITE_DAC,
1405                                             attr,
1406                                             objectclass);
1407         if (ret == LDB_SUCCESS) {
1408                 goto success;
1409         }
1410
1411         if (control_sd->specified_sd) {
1412                 bool block_owner_rights = dsdb_block_owner_implicit_rights(module,
1413                                                                            req,
1414                                                                            req);
1415                 if (block_owner_rights) {
1416                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
1417                                                "Object %s has no SD modification rights",
1418                                                ldb_dn_get_linearized(msg->dn));
1419                         dsdb_acl_debug(control_sd->default_sd,
1420                                        acl_user_token(module),
1421                                        msg->dn,
1422                                        true,
1423                                        10);
1424                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1425                         return ret;
1426                 }
1427         }
1428
1429         must_contain = dsdb_full_attribute_list(req, schema, &sorted_oc_el,
1430                                                 DSDB_SCHEMA_ALL_MUST);
1431         for (i=0; i < msg->num_elements; i++) {
1432                 el = &msg->elements[i];
1433
1434                 attr = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
1435                 if (attr == NULL && ldb_attr_cmp("clearTextPassword", el->name) != 0) {
1436                         ldb_asprintf_errstring(ldb, "acl_add: attribute '%s' "
1437                                                "on entry '%s' was not found in the schema!",
1438                                                el->name,
1439                                        ldb_dn_get_linearized(msg->dn));
1440                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
1441                         return ret;
1442                 }
1443
1444                 if (attr != NULL) {
1445                         bool found = str_list_check(must_contain, attr->lDAPDisplayName);
1446                         /* do not check the mandatory attributes */
1447                         if (found) {
1448                                 continue;
1449                         }
1450                 }
1451
1452                 if (ldb_attr_cmp("dBCSPwd", el->name) == 0 ||
1453                            ldb_attr_cmp("unicodePwd", el->name) == 0 ||
1454                            ldb_attr_cmp("userPassword", el->name) == 0 ||
1455                            ldb_attr_cmp("clearTextPassword", el->name) == 0) {
1456                         continue;
1457                 } else if (ldb_attr_cmp("member", el->name) == 0) {
1458                         ret = acl_check_self_membership(req,
1459                                                         module,
1460                                                         req,
1461                                                         control_sd->default_sd,
1462                                                         NULL,
1463                                                         attr,
1464                                                         objectclass);
1465                         if (ret != LDB_SUCCESS) {
1466                                 return ret;
1467                         }
1468                 } else if (ldb_attr_cmp("servicePrincipalName", el->name) == 0) {
1469                         ret = acl_check_spn(req,
1470                                             module,
1471                                             req,
1472                                             el,
1473                                             control_sd->default_sd,
1474                                             NULL,
1475                                             attr,
1476                                             objectclass,
1477                                             NULL);
1478                         if (ret != LDB_SUCCESS) {
1479                                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1480                                                        "Object %s cannot be created with spn",
1481                                                        ldb_dn_get_linearized(msg->dn));
1482                                 dsdb_acl_debug(control_sd->default_sd,
1483                                                acl_user_token(module),
1484                                                msg->dn,
1485                                                true,
1486                                                10);
1487                                 return ret;
1488                         }
1489                 } else if (ldb_attr_cmp("dnsHostName", el->name) == 0) {
1490                         ret = acl_check_dns_host_name(req,
1491                                                       module,
1492                                                       req,
1493                                                       el,
1494                                                       control_sd->default_sd,
1495                                                       NULL,
1496                                                       attr,
1497                                                       objectclass,
1498                                                       NULL);
1499                         if (ret != LDB_SUCCESS) {
1500                                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1501                                                        "Object %s cannot be created with dnsHostName",
1502                                                        ldb_dn_get_linearized(msg->dn));
1503                                 dsdb_acl_debug(control_sd->default_sd,
1504                                                acl_user_token(module),
1505                                                msg->dn,
1506                                                true,
1507                                                10);
1508                                 return ret;
1509                         }
1510                 } else {
1511                         ret = acl_check_access_on_attribute(module,
1512                                                             req,
1513                                                             control_sd->default_sd,
1514                                                             NULL,
1515                                                             SEC_ADS_WRITE_PROP,
1516                                                             attr,
1517                                                             objectclass);
1518                         if (ret != LDB_SUCCESS) {
1519                                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1520                                                        "Object %s has no write property access",
1521                                                        ldb_dn_get_linearized(msg->dn));
1522                                 dsdb_acl_debug(control_sd->default_sd,
1523                                                acl_user_token(module),
1524                                                msg->dn,
1525                                                true,
1526                                                10);
1527                                 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
1528                                 return ret;
1529                         }
1530                 }
1531         }
1532 success:
1533         return ldb_next_request(module, req);
1534 }
1535
1536 static int acl_check_password_rights(
1537         TALLOC_CTX *mem_ctx,
1538         struct ldb_module *module,
1539         struct ldb_request *req,
1540         struct security_descriptor *sd,
1541         struct dom_sid *sid,
1542         const struct dsdb_class *objectclass,
1543         bool userPassword,
1544         struct  dsdb_control_password_acl_validation **control_for_response)
1545 {
1546         int ret = LDB_SUCCESS;
1547         unsigned int del_attr_cnt = 0, add_attr_cnt = 0, rep_attr_cnt = 0;
1548         unsigned int del_val_cnt = 0, add_val_cnt = 0;
1549         struct ldb_message_element *el;
1550         struct ldb_message *msg;
1551         struct ldb_control *c = NULL;
1552         const char *passwordAttrs[] = { "userPassword", "clearTextPassword",
1553                                         "unicodePwd", NULL }, **l;
1554         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1555         struct dsdb_control_password_acl_validation *pav = NULL;
1556
1557         if (tmp_ctx == NULL) {
1558                 return LDB_ERR_OPERATIONS_ERROR;
1559         }
1560
1561         pav = talloc_zero(req, struct dsdb_control_password_acl_validation);
1562         if (pav == NULL) {
1563                 talloc_free(tmp_ctx);
1564                 return LDB_ERR_OPERATIONS_ERROR;
1565         }
1566         /*
1567          * Set control_for_response to pav so it can be added to the response
1568          * and be passed up to the audit_log module which uses it to identify
1569          * password reset attempts.
1570          */
1571         *control_for_response = pav;
1572
1573         c = ldb_request_get_control(req, DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID);
1574         if (c != NULL) {
1575                 pav->pwd_reset = false;
1576
1577                 /*
1578                  * The "DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID" control means that we
1579                  * have a user password change and not a set as the message
1580                  * looks like. In it's value blob it contains the NT and/or LM
1581                  * hash of the old password specified by the user.  This control
1582                  * is used by the SAMR and "kpasswd" password change mechanisms.
1583                  *
1584                  * This control can't be used by real LDAP clients,
1585                  * the only caller is samdb_set_password_internal(),
1586                  * so we don't have to strict verification of the input.
1587                  */
1588                 ret = acl_check_extended_right(tmp_ctx,
1589                                                module,
1590                                                req,
1591                                                objectclass,
1592                                                sd,
1593                                                acl_user_token(module),
1594                                                GUID_DRS_USER_CHANGE_PASSWORD,
1595                                                SEC_ADS_CONTROL_ACCESS,
1596                                                sid);
1597                 goto checked;
1598         }
1599
1600         c = ldb_request_get_control(req, DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
1601         if (c != NULL) {
1602                 pav->pwd_reset = true;
1603
1604                 /*
1605                  * The "DSDB_CONTROL_PASSWORD_HASH_VALUES_OID" control, without
1606                  * "DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID" control means that we
1607                  * have a force password set.
1608                  * This control is used by the SAMR/NETLOGON/LSA password
1609                  * reset mechanisms.
1610                  *
1611                  * This control can't be used by real LDAP clients,
1612                  * the only caller is samdb_set_password_internal(),
1613                  * so we don't have to strict verification of the input.
1614                  */
1615                 ret = acl_check_extended_right(tmp_ctx,
1616                                                module,
1617                                                req,
1618                                                objectclass,
1619                                                sd,
1620                                                acl_user_token(module),
1621                                                GUID_DRS_FORCE_CHANGE_PASSWORD,
1622                                                SEC_ADS_CONTROL_ACCESS,
1623                                                sid);
1624                 goto checked;
1625         }
1626
1627         el = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");
1628         if (el != NULL) {
1629                 /*
1630                  * dBCSPwd is only allowed with a control.
1631                  */
1632                 talloc_free(tmp_ctx);
1633                 return LDB_ERR_UNWILLING_TO_PERFORM;
1634         }
1635
1636         msg = ldb_msg_copy_shallow(tmp_ctx, req->op.mod.message);
1637         if (msg == NULL) {
1638                 return ldb_module_oom(module);
1639         }
1640         for (l = passwordAttrs; *l != NULL; l++) {
1641                 if ((!userPassword) && (ldb_attr_cmp(*l, "userPassword") == 0)) {
1642                         continue;
1643                 }
1644
1645                 while ((el = ldb_msg_find_element(msg, *l)) != NULL) {
1646                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
1647                                 ++del_attr_cnt;
1648                                 del_val_cnt += el->num_values;
1649                         }
1650                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD) {
1651                                 ++add_attr_cnt;
1652                                 add_val_cnt += el->num_values;
1653                         }
1654                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) {
1655                                 ++rep_attr_cnt;
1656                         }
1657                         ldb_msg_remove_element(msg, el);
1658                 }
1659         }
1660
1661         /* single deletes will be handled by the "password_hash" LDB module
1662          * later in the stack, so we let it though here */
1663         if ((del_attr_cnt > 0) && (add_attr_cnt == 0) && (rep_attr_cnt == 0)) {
1664                 talloc_free(tmp_ctx);
1665                 return LDB_SUCCESS;
1666         }
1667
1668
1669         if (rep_attr_cnt > 0) {
1670                 pav->pwd_reset = true;
1671
1672                 ret = acl_check_extended_right(tmp_ctx,
1673                                                module,
1674                                                req,
1675                                                objectclass,
1676                                                sd,
1677                                                acl_user_token(module),
1678                                                GUID_DRS_FORCE_CHANGE_PASSWORD,
1679                                                SEC_ADS_CONTROL_ACCESS,
1680                                                sid);
1681                 goto checked;
1682         }
1683
1684         if (add_attr_cnt != del_attr_cnt) {
1685                 pav->pwd_reset = true;
1686
1687                 ret = acl_check_extended_right(tmp_ctx,
1688                                                module,
1689                                                req,
1690                                                objectclass,
1691                                                sd,
1692                                                acl_user_token(module),
1693                                                GUID_DRS_FORCE_CHANGE_PASSWORD,
1694                                                SEC_ADS_CONTROL_ACCESS,
1695                                                sid);
1696                 goto checked;
1697         }
1698
1699         if (add_val_cnt == 1 && del_val_cnt == 1) {
1700                 pav->pwd_reset = false;
1701
1702                 ret = acl_check_extended_right(tmp_ctx,
1703                                                module,
1704                                                req,
1705                                                objectclass,
1706                                                sd,
1707                                                acl_user_token(module),
1708                                                GUID_DRS_USER_CHANGE_PASSWORD,
1709                                                SEC_ADS_CONTROL_ACCESS,
1710                                                sid);
1711                 /* Very strange, but we get constraint violation in this case */
1712                 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1713                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
1714                 }
1715                 goto checked;
1716         }
1717
1718         if (add_val_cnt == 1 && del_val_cnt == 0) {
1719                 pav->pwd_reset = true;
1720
1721                 ret = acl_check_extended_right(tmp_ctx,
1722                                                module,
1723                                                req,
1724                                                objectclass,
1725                                                sd,
1726                                                acl_user_token(module),
1727                                                GUID_DRS_FORCE_CHANGE_PASSWORD,
1728                                                SEC_ADS_CONTROL_ACCESS,
1729                                                sid);
1730                 /* Very strange, but we get constraint violation in this case */
1731                 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1732                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
1733                 }
1734                 goto checked;
1735         }
1736
1737         /*
1738          * Everything else is handled by the password_hash module where it will
1739          * fail, but with the correct error code when the module is again
1740          * checking the attributes. As the change request will lack the
1741          * DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID control, we can be sure that
1742          * any modification attempt that went this way will be rejected.
1743          */
1744
1745         talloc_free(tmp_ctx);
1746         return LDB_SUCCESS;
1747
1748 checked:
1749         if (ret != LDB_SUCCESS) {
1750                 dsdb_acl_debug(sd, acl_user_token(module),
1751                                req->op.mod.message->dn,
1752                                true,
1753                                10);
1754                 talloc_free(tmp_ctx);
1755                 return ret;
1756         }
1757
1758         ret = ldb_request_add_control(req,
1759                 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID, false, pav);
1760         if (ret != LDB_SUCCESS) {
1761                 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
1762                           "Unable to register ACL validation control!\n");
1763                 return ret;
1764         }
1765         return LDB_SUCCESS;
1766 }
1767
1768 /*
1769  * Context needed by acl_callback
1770  */
1771 struct acl_callback_context {
1772         struct ldb_request *request;
1773         struct ldb_module *module;
1774 };
1775
1776 /*
1777  * @brief Copy the password validation control to the reply.
1778  *
1779  * Copy the dsdb_control_password_acl_validation control from the request,
1780  * to the reply.  The control is used by the audit_log module to identify
1781  * password rests.
1782  *
1783  * @param req the ldb request.
1784  * @param ares the result, updated with the control.
1785  */
1786 static void copy_password_acl_validation_control(
1787         struct ldb_request *req,
1788         struct ldb_reply *ares)
1789 {
1790         struct ldb_control *pav_ctrl = NULL;
1791         struct dsdb_control_password_acl_validation *pav = NULL;
1792
1793         pav_ctrl = ldb_request_get_control(
1794                 discard_const(req),
1795                 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
1796         if (pav_ctrl == NULL) {
1797                 return;
1798         }
1799
1800         pav = talloc_get_type_abort(
1801                 pav_ctrl->data,
1802                 struct dsdb_control_password_acl_validation);
1803         if (pav == NULL) {
1804                 return;
1805         }
1806         ldb_reply_add_control(
1807                 ares,
1808                 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID,
1809                 false,
1810                 pav);
1811 }
1812 /*
1813  * @brief call back function for acl_modify.
1814  *
1815  * Calls acl_copy to copy the dsdb_control_password_acl_validation from
1816  * the request to the reply.
1817  *
1818  * @param req the ldb_request.
1819  * @param ares the operation result.
1820  *
1821  * @return the LDB_STATUS
1822  */
1823 static int acl_callback(struct ldb_request *req, struct ldb_reply *ares)
1824 {
1825         struct acl_callback_context *ac = NULL;
1826
1827         ac = talloc_get_type(req->context, struct acl_callback_context);
1828
1829         if (!ares) {
1830                 return ldb_module_done(
1831                         ac->request,
1832                         NULL,
1833                         NULL,
1834                         LDB_ERR_OPERATIONS_ERROR);
1835         }
1836
1837         /* pass on to the callback */
1838         switch (ares->type) {
1839         case LDB_REPLY_ENTRY:
1840                 return ldb_module_send_entry(
1841                         ac->request,
1842                         ares->message,
1843                         ares->controls);
1844
1845         case LDB_REPLY_REFERRAL:
1846                 return ldb_module_send_referral(
1847                         ac->request,
1848                         ares->referral);
1849
1850         case LDB_REPLY_DONE:
1851                 /*
1852                  * Copy the ACL control from the request to the response
1853                  */
1854                 copy_password_acl_validation_control(req, ares);
1855                 return ldb_module_done(
1856                         ac->request,
1857                         ares->controls,
1858                         ares->response,
1859                         ares->error);
1860
1861         default:
1862                 /* Can't happen */
1863                 return LDB_ERR_OPERATIONS_ERROR;
1864         }
1865 }
1866
1867 static int acl_modify(struct ldb_module *module, struct ldb_request *req)
1868 {
1869         int ret;
1870         struct ldb_context *ldb = ldb_module_get_ctx(module);
1871         const struct dsdb_schema *schema;
1872         unsigned int i;
1873         const struct dsdb_class *objectclass;
1874         struct ldb_result *acl_res;
1875         struct security_descriptor *sd;
1876         struct dom_sid *sid = NULL;
1877         struct ldb_control *is_undelete;
1878         struct ldb_control *implicit_validated_write_control = NULL;
1879         bool userPassword;
1880         bool password_rights_checked = false;
1881         TALLOC_CTX *tmp_ctx;
1882         const struct ldb_message *msg = req->op.mod.message;
1883         static const char *acl_attrs[] = {
1884                 "nTSecurityDescriptor",
1885                 "objectClass",
1886                 "objectSid",
1887                 NULL
1888         };
1889         struct acl_callback_context *context = NULL;
1890         struct ldb_request *new_req = NULL;
1891         struct  dsdb_control_password_acl_validation *pav = NULL;
1892         struct ldb_control **controls = NULL;
1893
1894         if (ldb_dn_is_special(msg->dn)) {
1895                 return ldb_next_request(module, req);
1896         }
1897
1898         is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
1899
1900         implicit_validated_write_control = ldb_request_get_control(
1901                 req, DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID);
1902         if (implicit_validated_write_control != NULL) {
1903                 implicit_validated_write_control->critical = 0;
1904         }
1905
1906         /* Don't print this debug statement if elements[0].name is going to be NULL */
1907         if (msg->num_elements > 0) {
1908                 DEBUG(10, ("ldb:acl_modify: %s\n", msg->elements[0].name));
1909         }
1910         if (dsdb_have_system_access(module, req, SYSTEM_CONTROL_STRIP_CRITICAL))
1911         {
1912                 return ldb_next_request(module, req);
1913         }
1914
1915         tmp_ctx = talloc_new(req);
1916         if (tmp_ctx == NULL) {
1917                 return ldb_oom(ldb);
1918         }
1919
1920         ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res, msg->dn,
1921                                     acl_attrs,
1922                                     DSDB_FLAG_NEXT_MODULE |
1923                                     DSDB_FLAG_AS_SYSTEM |
1924                                     DSDB_SEARCH_SHOW_RECYCLED,
1925                                     req);
1926
1927         if (ret != LDB_SUCCESS) {
1928                 goto fail;
1929         }
1930
1931         userPassword = dsdb_user_password_support(module, req, req);
1932
1933         schema = dsdb_get_schema(ldb, tmp_ctx);
1934         if (!schema) {
1935                 talloc_free(tmp_ctx);
1936                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
1937                                  "acl_modify: Error obtaining schema.");
1938         }
1939
1940         ret = dsdb_get_sd_from_ldb_message(ldb, tmp_ctx, acl_res->msgs[0], &sd);
1941         if (ret != LDB_SUCCESS) {
1942                 talloc_free(tmp_ctx);
1943                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
1944                                  "acl_modify: Error retrieving security descriptor.");
1945         }
1946         /* Theoretically we pass the check if the object has no sd */
1947         if (!sd) {
1948                 goto success;
1949         }
1950
1951         objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]);
1952         if (!objectclass) {
1953                 talloc_free(tmp_ctx);
1954                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
1955                                  "acl_modify: Error retrieving object class for GUID.");
1956         }
1957         sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid");
1958         for (i=0; i < msg->num_elements; i++) {
1959                 const struct ldb_message_element *el = &msg->elements[i];
1960                 const struct dsdb_attribute *attr;
1961
1962                 /*
1963                  * This basic attribute existence check with the right errorcode
1964                  * is needed since this module is the first one which requests
1965                  * schema attribute information.
1966                  * The complete attribute checking is done in the
1967                  * "objectclass_attrs" module behind this one.
1968                  *
1969                  * NOTE: "clearTextPassword" is not defined in the schema.
1970                  */
1971                 attr = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
1972                 if (!attr && ldb_attr_cmp("clearTextPassword", el->name) != 0) {
1973                         ldb_asprintf_errstring(ldb, "acl_modify: attribute '%s' "
1974                                                "on entry '%s' was not found in the schema!",
1975                                                req->op.mod.message->elements[i].name,
1976                                        ldb_dn_get_linearized(req->op.mod.message->dn));
1977                         ret =  LDB_ERR_NO_SUCH_ATTRIBUTE;
1978                         goto fail;
1979                 }
1980
1981                 if (ldb_attr_cmp("nTSecurityDescriptor", el->name) == 0) {
1982                         uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
1983                         uint32_t access_mask = 0;
1984
1985                         bool block_owner_rights;
1986                         enum implicit_owner_rights implicit_owner_rights;
1987
1988                         if (sd_flags & (SECINFO_OWNER|SECINFO_GROUP)) {
1989                                 access_mask |= SEC_STD_WRITE_OWNER;
1990                         }
1991                         if (sd_flags & SECINFO_DACL) {
1992                                 access_mask |= SEC_STD_WRITE_DAC;
1993                         }
1994                         if (sd_flags & SECINFO_SACL) {
1995                                 access_mask |= SEC_FLAG_SYSTEM_SECURITY;
1996                         }
1997
1998                         block_owner_rights = !dsdb_module_am_administrator(module);
1999
2000                         if (block_owner_rights) {
2001                                 block_owner_rights = dsdb_block_owner_implicit_rights(module,
2002                                                                                       req,
2003                                                                                       req);
2004                         }
2005                         if (block_owner_rights) {
2006                                 block_owner_rights = samdb_find_attribute(ldb,
2007                                                                           acl_res->msgs[0],
2008                                                                           "objectclass",
2009                                                                           "computer");
2010                         }
2011
2012                         implicit_owner_rights = block_owner_rights ?
2013                                 IMPLICIT_OWNER_READ_CONTROL_RIGHTS :
2014                                 IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS;
2015
2016                         ret = acl_check_access_on_attribute_implicit_owner(module,
2017                                                                            tmp_ctx,
2018                                                                            sd,
2019                                                                            sid,
2020                                                                            access_mask,
2021                                                                            attr,
2022                                                                            objectclass,
2023                                                                            implicit_owner_rights);
2024                         if (ret != LDB_SUCCESS) {
2025                                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2026                                                        "Object %s has no write dacl access\n",
2027                                                        ldb_dn_get_linearized(msg->dn));
2028                                 dsdb_acl_debug(sd,
2029                                                acl_user_token(module),
2030                                                msg->dn,
2031                                                true,
2032                                                10);
2033                                 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2034                                 goto fail;
2035                         }
2036                 } else if (ldb_attr_cmp("member", el->name) == 0) {
2037                         ret = acl_check_self_membership(tmp_ctx,
2038                                                         module,
2039                                                         req,
2040                                                         sd,
2041                                                         sid,
2042                                                         attr,
2043                                                         objectclass);
2044                         if (ret != LDB_SUCCESS) {
2045                                 goto fail;
2046                         }
2047                 } else if (ldb_attr_cmp("dBCSPwd", el->name) == 0) {
2048                         /* this one is not affected by any rights, we should let it through
2049                            so that passwords_hash returns the correct error */
2050                         continue;
2051                 } else if (ldb_attr_cmp("unicodePwd", el->name) == 0 ||
2052                            (userPassword && ldb_attr_cmp("userPassword", el->name) == 0) ||
2053                            ldb_attr_cmp("clearTextPassword", el->name) == 0) {
2054                         /*
2055                          * Ideally we would do the acl_check_password_rights
2056                          * before we checked the other attributes, i.e. in a
2057                          * loop before the current one.
2058                          * Have not done this as yet in order to limit the size
2059                          * of the change. To limit the possibility of breaking
2060                          * the ACL logic.
2061                          */
2062                         if (password_rights_checked) {
2063                                 continue;
2064                         }
2065                         ret = acl_check_password_rights(tmp_ctx,
2066                                                         module,
2067                                                         req,
2068                                                         sd,
2069                                                         sid,
2070                                                         objectclass,
2071                                                         userPassword,
2072                                                         &pav);
2073                         if (ret != LDB_SUCCESS) {
2074                                 goto fail;
2075                         }
2076                         password_rights_checked = true;
2077                 } else if (ldb_attr_cmp("servicePrincipalName", el->name) == 0) {
2078                         ret = acl_check_spn(tmp_ctx,
2079                                             module,
2080                                             req,
2081                                             el,
2082                                             sd,
2083                                             sid,
2084                                             attr,
2085                                             objectclass,
2086                                             implicit_validated_write_control);
2087                         if (ret != LDB_SUCCESS) {
2088                                 goto fail;
2089                         }
2090                 } else if (ldb_attr_cmp("dnsHostName", el->name) == 0) {
2091                         ret = acl_check_dns_host_name(tmp_ctx,
2092                                                       module,
2093                                                       req,
2094                                                       el,
2095                                                       sd,
2096                                                       sid,
2097                                                       attr,
2098                                                       objectclass,
2099                                                       implicit_validated_write_control);
2100                         if (ret != LDB_SUCCESS) {
2101                                 goto fail;
2102                         }
2103                 } else if (is_undelete != NULL && (ldb_attr_cmp("isDeleted", el->name) == 0)) {
2104                         /*
2105                          * in case of undelete op permissions on
2106                          * isDeleted are irrelevant and
2107                          * distinguishedName is removed by the
2108                          * tombstone_reanimate module
2109                          */
2110                         continue;
2111                 } else if (implicit_validated_write_control != NULL) {
2112                         /* Allow the update. */
2113                         continue;
2114                 } else {
2115                         ret = acl_check_access_on_attribute(module,
2116                                                             tmp_ctx,
2117                                                             sd,
2118                                                             sid,
2119                                                             SEC_ADS_WRITE_PROP,
2120                                                             attr,
2121                                                             objectclass);
2122                         if (ret != LDB_SUCCESS) {
2123                                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2124                                                        "Object %s has no write property access\n",
2125                                                        ldb_dn_get_linearized(msg->dn));
2126                                 dsdb_acl_debug(sd,
2127                                                acl_user_token(module),
2128                                                msg->dn,
2129                                                true,
2130                                                10);
2131                                 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2132                                 goto fail;
2133                         }
2134                 }
2135         }
2136
2137 success:
2138         talloc_free(tmp_ctx);
2139         context = talloc_zero(req, struct acl_callback_context);
2140
2141         if (context == NULL) {
2142                 return ldb_oom(ldb);
2143         }
2144         context->request = req;
2145         context->module  = module;
2146         ret = ldb_build_mod_req(
2147                 &new_req,
2148                 ldb,
2149                 req,
2150                 req->op.mod.message,
2151                 req->controls,
2152                 context,
2153                 acl_callback,
2154                 req);
2155         if (ret != LDB_SUCCESS) {
2156                 return ret;
2157         }
2158         return ldb_next_request(module, new_req);
2159 fail:
2160         talloc_free(tmp_ctx);
2161         /*
2162          * We copy the pav into the result, so that the password reset
2163          * logging code in audit_log can log failed password reset attempts.
2164          */
2165         if (pav) {
2166                 struct ldb_control *control = NULL;
2167
2168                 controls = talloc_zero_array(req, struct ldb_control *, 2);
2169                 if (controls == NULL) {
2170                         return ldb_oom(ldb);
2171                 }
2172
2173                 control = talloc(controls, struct ldb_control);
2174
2175                 if (control == NULL) {
2176                         return ldb_oom(ldb);
2177                 }
2178
2179                 control->oid= talloc_strdup(
2180                         control,
2181                         DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
2182                 if (control->oid == NULL) {
2183                         return ldb_oom(ldb);
2184                 }
2185                 control->critical       = false;
2186                 control->data   = pav;
2187                 *controls = control;
2188         }
2189         return ldb_module_done(req, controls, NULL, ret);
2190 }
2191
2192 /* similar to the modify for the time being.
2193  * We need to consider the special delete tree case, though - TODO */
2194 static int acl_delete(struct ldb_module *module, struct ldb_request *req)
2195 {
2196         int ret;
2197         struct ldb_dn *parent;
2198         struct ldb_context *ldb;
2199         struct ldb_dn *nc_root;
2200         const struct dsdb_schema *schema;
2201         const struct dsdb_class *objectclass;
2202         struct security_descriptor *sd = NULL;
2203         struct dom_sid *sid = NULL;
2204         struct ldb_result *acl_res;
2205         static const char *acl_attrs[] = {
2206                 "nTSecurityDescriptor",
2207                 "objectClass",
2208                 "objectSid",
2209                 NULL
2210         };
2211
2212         if (ldb_dn_is_special(req->op.del.dn)) {
2213                 return ldb_next_request(module, req);
2214         }
2215
2216         if (dsdb_have_system_access(module, req, SYSTEM_CONTROL_STRIP_CRITICAL))
2217         {
2218                 return ldb_next_request(module, req);
2219         }
2220
2221         DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn)));
2222
2223         ldb = ldb_module_get_ctx(module);
2224
2225         parent = ldb_dn_get_parent(req, req->op.del.dn);
2226         if (parent == NULL) {
2227                 return ldb_oom(ldb);
2228         }
2229
2230         /* Make sure we aren't deleting a NC */
2231
2232         ret = dsdb_find_nc_root(ldb, req, req->op.del.dn, &nc_root);
2233         if (ret != LDB_SUCCESS) {
2234                 return ret;
2235         }
2236         if (ldb_dn_compare(nc_root, req->op.del.dn) == 0) {
2237                 talloc_free(nc_root);
2238                 DEBUG(10,("acl:deleting a NC\n"));
2239                 /* Windows returns "ERR_UNWILLING_TO_PERFORM */
2240                 return ldb_module_done(req, NULL, NULL,
2241                                        LDB_ERR_UNWILLING_TO_PERFORM);
2242         }
2243         talloc_free(nc_root);
2244
2245         ret = dsdb_module_search_dn(module, req, &acl_res,
2246                                     req->op.del.dn, acl_attrs,
2247                                     DSDB_FLAG_NEXT_MODULE |
2248                                     DSDB_FLAG_AS_SYSTEM |
2249                                     DSDB_SEARCH_SHOW_RECYCLED, req);
2250         /* we should be able to find the parent */
2251         if (ret != LDB_SUCCESS) {
2252                 DEBUG(10,("acl: failed to find object %s\n",
2253                           ldb_dn_get_linearized(req->op.rename.olddn)));
2254                 return ret;
2255         }
2256
2257         ret = dsdb_get_sd_from_ldb_message(ldb, req, acl_res->msgs[0], &sd);
2258         if (ret != LDB_SUCCESS) {
2259                 return ldb_operr(ldb);
2260         }
2261         if (!sd) {
2262                 return ldb_operr(ldb);
2263         }
2264
2265         schema = dsdb_get_schema(ldb, req);
2266         if (!schema) {
2267                 return ldb_operr(ldb);
2268         }
2269
2270         sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid");
2271
2272         objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]);
2273         if (!objectclass) {
2274                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
2275                                  "acl_modify: Error retrieving object class for GUID.");
2276         }
2277
2278         if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID)) {
2279                 ret = acl_check_access_on_objectclass(module, req, sd, sid,
2280                                                       SEC_ADS_DELETE_TREE,
2281                                                       objectclass);
2282                 if (ret != LDB_SUCCESS) {
2283                         return ret;
2284                 }
2285
2286                 return ldb_next_request(module, req);
2287         }
2288
2289         /* First check if we have delete object right */
2290         ret = acl_check_access_on_objectclass(module, req, sd, sid,
2291                                               SEC_STD_DELETE,
2292                                               objectclass);
2293         if (ret == LDB_SUCCESS) {
2294                 return ldb_next_request(module, req);
2295         }
2296
2297         /* Nope, we don't have delete object. Lets check if we have delete
2298          * child on the parent */
2299         ret = dsdb_module_check_access_on_dn(module, req, parent,
2300                                              SEC_ADS_DELETE_CHILD,
2301                                              &objectclass->schemaIDGUID,
2302                                              req);
2303         if (ret != LDB_SUCCESS) {
2304                 return ret;
2305         }
2306
2307         return ldb_next_request(module, req);
2308 }
2309 static int acl_check_reanimate_tombstone(TALLOC_CTX *mem_ctx,
2310                                          struct ldb_module *module,
2311                                          struct ldb_request *req,
2312                                          struct ldb_dn *nc_root)
2313 {
2314         int ret;
2315         struct ldb_result *acl_res;
2316         struct security_descriptor *sd = NULL;
2317         struct dom_sid *sid = NULL;
2318         const struct dsdb_schema *schema = NULL;
2319         const struct dsdb_class *objectclass = NULL;
2320         struct ldb_context *ldb = ldb_module_get_ctx(module);
2321         static const char *acl_attrs[] = {
2322                 "nTSecurityDescriptor",
2323                 "objectClass",
2324                 "objectSid",
2325                 NULL
2326         };
2327
2328         ret = dsdb_module_search_dn(module, mem_ctx, &acl_res,
2329                                     nc_root, acl_attrs,
2330                                     DSDB_FLAG_NEXT_MODULE |
2331                                     DSDB_FLAG_AS_SYSTEM |
2332                                     DSDB_SEARCH_SHOW_RECYCLED, req);
2333         if (ret != LDB_SUCCESS) {
2334                 DEBUG(10,("acl: failed to find object %s\n",
2335                           ldb_dn_get_linearized(nc_root)));
2336                 return ret;
2337         }
2338
2339         ret = dsdb_get_sd_from_ldb_message(mem_ctx, req, acl_res->msgs[0], &sd);
2340         sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid");
2341         schema = dsdb_get_schema(ldb, req);
2342         if (!schema) {
2343                 return LDB_ERR_OPERATIONS_ERROR;
2344         }
2345         objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]);
2346         if (ret != LDB_SUCCESS || !sd) {
2347                 return ldb_operr(ldb_module_get_ctx(module));
2348         }
2349         return acl_check_extended_right(mem_ctx,
2350                                         module,
2351                                         req,
2352                                         objectclass,
2353                                         sd,
2354                                         acl_user_token(module),
2355                                         GUID_DRS_REANIMATE_TOMBSTONE,
2356                                         SEC_ADS_CONTROL_ACCESS, sid);
2357 }
2358
2359 static int acl_rename(struct ldb_module *module, struct ldb_request *req)
2360 {
2361         int ret;
2362         struct ldb_dn *oldparent;
2363         struct ldb_dn *newparent;
2364         const struct dsdb_schema *schema;
2365         const struct dsdb_class *objectclass;
2366         const struct dsdb_attribute *attr = NULL;
2367         struct ldb_context *ldb;
2368         struct security_descriptor *sd = NULL;
2369         struct dom_sid *sid = NULL;
2370         struct ldb_result *acl_res;
2371         struct ldb_dn *nc_root;
2372         struct ldb_control *is_undelete;
2373         TALLOC_CTX *tmp_ctx;
2374         const char *rdn_name;
2375         static const char *acl_attrs[] = {
2376                 "nTSecurityDescriptor",
2377                 "objectClass",
2378                 "objectSid",
2379                 NULL
2380         };
2381
2382         if (ldb_dn_is_special(req->op.rename.olddn)) {
2383                 return ldb_next_request(module, req);
2384         }
2385
2386         DEBUG(10, ("ldb:acl_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)));
2387         if (dsdb_have_system_access(module, req, SYSTEM_CONTROL_STRIP_CRITICAL))
2388         {
2389                 return ldb_next_request(module, req);
2390         }
2391
2392         ldb = ldb_module_get_ctx(module);
2393
2394         tmp_ctx = talloc_new(req);
2395         if (tmp_ctx == NULL) {
2396                 return ldb_oom(ldb);
2397         }
2398
2399         oldparent = ldb_dn_get_parent(tmp_ctx, req->op.rename.olddn);
2400         if (oldparent == NULL) {
2401                 return ldb_oom(ldb);
2402         }
2403         newparent = ldb_dn_get_parent(tmp_ctx, req->op.rename.newdn);
2404         if (newparent == NULL) {
2405                 return ldb_oom(ldb);
2406         }
2407
2408         /* Make sure we aren't renaming/moving a NC */
2409
2410         ret = dsdb_find_nc_root(ldb, req, req->op.rename.olddn, &nc_root);
2411         if (ret != LDB_SUCCESS) {
2412                 return ret;
2413         }
2414         if (ldb_dn_compare(nc_root, req->op.rename.olddn) == 0) {
2415                 talloc_free(nc_root);
2416                 DEBUG(10,("acl:renaming/moving a NC\n"));
2417                 /* Windows returns "ERR_UNWILLING_TO_PERFORM */
2418                 return ldb_module_done(req, NULL, NULL,
2419                                        LDB_ERR_UNWILLING_TO_PERFORM);
2420         }
2421
2422         /* special check for undelete operation */
2423         is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
2424         if (is_undelete != NULL) {
2425                 is_undelete->critical = 0;
2426                 ret = acl_check_reanimate_tombstone(tmp_ctx, module, req, nc_root);
2427                 if (ret != LDB_SUCCESS) {
2428                         talloc_free(tmp_ctx);
2429                         return ret;
2430                 }
2431         }
2432         talloc_free(nc_root);
2433
2434         /* Look for the parent */
2435
2436         ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res,
2437                                     req->op.rename.olddn, acl_attrs,
2438                                     DSDB_FLAG_NEXT_MODULE |
2439                                     DSDB_FLAG_AS_SYSTEM |
2440                                     DSDB_SEARCH_SHOW_RECYCLED, req);
2441         /* we should be able to find the parent */
2442         if (ret != LDB_SUCCESS) {
2443                 DEBUG(10,("acl: failed to find object %s\n",
2444                           ldb_dn_get_linearized(req->op.rename.olddn)));
2445                 talloc_free(tmp_ctx);
2446                 return ret;
2447         }
2448
2449         ret = dsdb_get_sd_from_ldb_message(ldb, req, acl_res->msgs[0], &sd);
2450         if (ret != LDB_SUCCESS) {
2451                 talloc_free(tmp_ctx);
2452                 return ldb_operr(ldb);
2453         }
2454         if (!sd) {
2455                 talloc_free(tmp_ctx);
2456                 return ldb_operr(ldb);
2457         }
2458
2459         schema = dsdb_get_schema(ldb, acl_res);
2460         if (!schema) {
2461                 talloc_free(tmp_ctx);
2462                 return ldb_operr(ldb);
2463         }
2464
2465         sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid");
2466
2467         objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]);
2468         if (!objectclass) {
2469                 talloc_free(tmp_ctx);
2470                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
2471                                  "acl_modify: Error retrieving object class for GUID.");
2472         }
2473
2474         attr = dsdb_attribute_by_lDAPDisplayName(schema, "name");
2475         if (attr == NULL) {
2476                 talloc_free(tmp_ctx);
2477                 return ldb_operr(ldb);
2478         }
2479
2480         ret = acl_check_access_on_attribute(module, tmp_ctx, sd, sid,
2481                                             SEC_ADS_WRITE_PROP,
2482                                             attr, objectclass);
2483         if (ret != LDB_SUCCESS) {
2484                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2485                                        "Object %s has no wp on %s\n",
2486                                        ldb_dn_get_linearized(req->op.rename.olddn),
2487                                        attr->lDAPDisplayName);
2488                 dsdb_acl_debug(sd,
2489                           acl_user_token(module),
2490                           req->op.rename.olddn,
2491                           true,
2492                           10);
2493                 talloc_free(tmp_ctx);
2494                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2495         }
2496
2497         rdn_name = ldb_dn_get_rdn_name(req->op.rename.olddn);
2498         if (rdn_name == NULL) {
2499                 talloc_free(tmp_ctx);
2500                 return ldb_operr(ldb);
2501         }
2502
2503         attr = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
2504         if (attr == NULL) {
2505                 talloc_free(tmp_ctx);
2506                 return ldb_operr(ldb);
2507         }
2508
2509         ret = acl_check_access_on_attribute(module, tmp_ctx, sd, sid,
2510                                             SEC_ADS_WRITE_PROP,
2511                                             attr, objectclass);
2512         if (ret != LDB_SUCCESS) {
2513                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2514                                        "Object %s has no wp on %s\n",
2515                                        ldb_dn_get_linearized(req->op.rename.olddn),
2516                                        attr->lDAPDisplayName);
2517                 dsdb_acl_debug(sd,
2518                           acl_user_token(module),
2519                           req->op.rename.olddn,
2520                           true,
2521                           10);
2522                 talloc_free(tmp_ctx);
2523                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2524         }
2525
2526         if (ldb_dn_compare(oldparent, newparent) == 0) {
2527                 /* regular rename, not move, nothing more to do */
2528                 talloc_free(tmp_ctx);
2529                 return ldb_next_request(module, req);
2530         }
2531
2532         /* new parent should have create child */
2533         ret = dsdb_module_check_access_on_dn(module, req, newparent,
2534                                              SEC_ADS_CREATE_CHILD,
2535                                              &objectclass->schemaIDGUID, req);
2536         if (ret != LDB_SUCCESS) {
2537                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2538                                        "acl:access_denied renaming %s",
2539                                        ldb_dn_get_linearized(req->op.rename.olddn));
2540                 talloc_free(tmp_ctx);
2541                 return ret;
2542         }
2543
2544         /* do we have delete object on the object? */
2545         /* this access is not necessary for undelete ops */
2546         if (is_undelete == NULL) {
2547                 ret = acl_check_access_on_objectclass(module, tmp_ctx, sd, sid,
2548                                                       SEC_STD_DELETE,
2549                                                       objectclass);
2550                 if (ret == LDB_SUCCESS) {
2551                         talloc_free(tmp_ctx);
2552                         return ldb_next_request(module, req);
2553                 }
2554                 /* what about delete child on the current parent */
2555                 ret = dsdb_module_check_access_on_dn(module, req, oldparent,
2556                                                      SEC_ADS_DELETE_CHILD,
2557                                                      &objectclass->schemaIDGUID,
2558                                                      req);
2559                 if (ret != LDB_SUCCESS) {
2560                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
2561                                                "acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn));
2562                         talloc_free(tmp_ctx);
2563                         return ldb_module_done(req, NULL, NULL, ret);
2564                 }
2565         }
2566         talloc_free(tmp_ctx);
2567
2568         return ldb_next_request(module, req);
2569 }
2570
2571 static int acl_search_update_confidential_attrs(struct acl_context *ac,
2572                                                 struct acl_private *data)
2573 {
2574         struct dsdb_attribute *a;
2575         uint32_t n = 0;
2576
2577         if (data->acl_search) {
2578                 /*
2579                  * If acl:search is activated, the acl_read module
2580                  * protects confidential attributes.
2581                  */
2582                 return LDB_SUCCESS;
2583         }
2584
2585         if ((ac->schema == data->cached_schema_ptr) &&
2586             (ac->schema->metadata_usn == data->cached_schema_metadata_usn))
2587         {
2588                 return LDB_SUCCESS;
2589         }
2590
2591         data->cached_schema_ptr = NULL;
2592         data->cached_schema_loaded_usn = 0;
2593         data->cached_schema_metadata_usn = 0;
2594         TALLOC_FREE(data->confidential_attrs);
2595
2596         if (ac->schema == NULL) {
2597                 return LDB_SUCCESS;
2598         }
2599
2600         for (a = ac->schema->attributes; a; a = a->next) {
2601                 const char **attrs = data->confidential_attrs;
2602
2603                 if (!(a->searchFlags & SEARCH_FLAG_CONFIDENTIAL)) {
2604                         continue;
2605                 }
2606
2607                 attrs = talloc_realloc(data, attrs, const char *, n + 2);
2608                 if (attrs == NULL) {
2609                         TALLOC_FREE(data->confidential_attrs);
2610                         return ldb_module_oom(ac->module);
2611                 }
2612
2613                 attrs[n] = a->lDAPDisplayName;
2614                 attrs[n+1] = NULL;
2615                 n++;
2616
2617                 data->confidential_attrs = attrs;
2618         }
2619
2620         data->cached_schema_ptr = ac->schema;
2621         data->cached_schema_metadata_usn = ac->schema->metadata_usn;
2622
2623         return LDB_SUCCESS;
2624 }
2625
2626 static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares)
2627 {
2628         struct acl_context *ac;
2629         struct acl_private *data;
2630         struct ldb_result *acl_res;
2631         static const char *acl_attrs[] = {
2632                 "objectClass",
2633                 "nTSecurityDescriptor",
2634                 "objectSid",
2635                 NULL
2636         };
2637         int ret;
2638         unsigned int i;
2639
2640         ac = talloc_get_type(req->context, struct acl_context);
2641         data = talloc_get_type(ldb_module_get_private(ac->module), struct acl_private);
2642         if (!ares) {
2643                 return ldb_module_done(ac->req, NULL, NULL,
2644                                        LDB_ERR_OPERATIONS_ERROR);
2645         }
2646         if (ares->error != LDB_SUCCESS) {
2647                 return ldb_module_done(ac->req, ares->controls,
2648                                        ares->response, ares->error);
2649         }
2650
2651         switch (ares->type) {
2652         case LDB_REPLY_ENTRY:
2653                 if (ac->constructed_attrs) {
2654                         ret = dsdb_module_search_dn(ac->module, ac, &acl_res, ares->message->dn,
2655                                                     acl_attrs,
2656                                                     DSDB_FLAG_NEXT_MODULE |
2657                                                     DSDB_FLAG_AS_SYSTEM |
2658                                                     DSDB_SEARCH_SHOW_RECYCLED,
2659                                                     req);
2660                         if (ret != LDB_SUCCESS) {
2661                                 return ldb_module_done(ac->req, NULL, NULL, ret);
2662                         }
2663                 }
2664
2665                 if (ac->allowedAttributes || ac->allowedAttributesEffective) {
2666                         ret = acl_allowedAttributes(ac->module, ac->schema,
2667                                                     acl_res->msgs[0],
2668                                                     ares->message, ac);
2669                         if (ret != LDB_SUCCESS) {
2670                                 return ldb_module_done(ac->req, NULL, NULL, ret);
2671                         }
2672                 }
2673
2674                 if (ac->allowedChildClasses) {
2675                         ret = acl_childClasses(ac->module, ac->schema,
2676                                                acl_res->msgs[0],
2677                                                ares->message,
2678                                                "allowedChildClasses");
2679                         if (ret != LDB_SUCCESS) {
2680                                 return ldb_module_done(ac->req, NULL, NULL, ret);
2681                         }
2682                 }
2683
2684                 if (ac->allowedChildClassesEffective) {
2685                         ret = acl_childClassesEffective(ac->module, ac->schema,
2686                                                         acl_res->msgs[0],
2687                                                         ares->message, ac);
2688                         if (ret != LDB_SUCCESS) {
2689                                 return ldb_module_done(ac->req, NULL, NULL, ret);
2690                         }
2691                 }
2692
2693                 if (ac->sDRightsEffective) {
2694                         ret = acl_sDRightsEffective(ac->module,
2695                                                     acl_res->msgs[0],
2696                                                     ares->message, ac);
2697                         if (ret != LDB_SUCCESS) {
2698                                 return ldb_module_done(ac->req, NULL, NULL, ret);
2699                         }
2700                 }
2701
2702                 if (data == NULL) {
2703                         return ldb_module_send_entry(ac->req, ares->message,
2704                                                      ares->controls);
2705                 }
2706
2707                 if (ac->am_system) {
2708                         return ldb_module_send_entry(ac->req, ares->message,
2709                                                      ares->controls);
2710                 }
2711
2712                 if (ac->am_administrator) {
2713                         return ldb_module_send_entry(ac->req, ares->message,
2714                                                      ares->controls);
2715                 }
2716
2717                 if (data->confidential_attrs != NULL) {
2718                         for (i = 0; data->confidential_attrs[i]; i++) {
2719                                 ldb_msg_remove_attr(ares->message,
2720                                                     data->confidential_attrs[i]);
2721                         }
2722                 }
2723
2724                 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
2725
2726         case LDB_REPLY_REFERRAL:
2727                 return ldb_module_send_referral(ac->req, ares->referral);
2728
2729         case LDB_REPLY_DONE:
2730                 return ldb_module_done(ac->req, ares->controls,
2731                                        ares->response, LDB_SUCCESS);
2732
2733         }
2734         return LDB_SUCCESS;
2735 }
2736
2737 static int acl_search(struct ldb_module *module, struct ldb_request *req)
2738 {
2739         struct ldb_context *ldb;
2740         struct acl_context *ac;
2741         struct ldb_parse_tree *down_tree = req->op.search.tree;
2742         struct ldb_request *down_req;
2743         struct acl_private *data;
2744         int ret;
2745         unsigned int i;
2746         bool modify_search = true;
2747
2748         if (ldb_dn_is_special(req->op.search.base)) {
2749                 return ldb_next_request(module, req);
2750         }
2751
2752         ldb = ldb_module_get_ctx(module);
2753
2754         ac = talloc_zero(req, struct acl_context);
2755         if (ac == NULL) {
2756                 return ldb_oom(ldb);
2757         }
2758         data = talloc_get_type(ldb_module_get_private(module), struct acl_private);
2759
2760         ac->module = module;
2761         ac->req = req;
2762         ac->am_system = dsdb_module_am_system(module);
2763         ac->am_administrator = dsdb_module_am_administrator(module);
2764         ac->constructed_attrs = false;
2765         ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes");
2766         ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective");
2767         ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses");
2768         ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective");
2769         ac->sDRightsEffective = ldb_attr_in_list(req->op.search.attrs, "sDRightsEffective");
2770         ac->schema = dsdb_get_schema(ldb, ac);
2771
2772         ac->constructed_attrs |= ac->allowedAttributes;
2773         ac->constructed_attrs |= ac->allowedChildClasses;
2774         ac->constructed_attrs |= ac->allowedChildClassesEffective;
2775         ac->constructed_attrs |= ac->allowedAttributesEffective;
2776         ac->constructed_attrs |= ac->sDRightsEffective;
2777
2778         if (data == NULL) {
2779                 modify_search = false;
2780         }
2781         if (ac->am_system) {
2782                 modify_search = false;
2783         }
2784
2785         if (!ac->constructed_attrs && !modify_search) {
2786                 talloc_free(ac);
2787                 return ldb_next_request(module, req);
2788         }
2789
2790         data = talloc_get_type(ldb_module_get_private(ac->module), struct acl_private);
2791         if (data == NULL) {
2792                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
2793                                  "acl_private data is missing");
2794         }
2795
2796         if (!ac->am_system && !ac->am_administrator) {
2797                 ret = acl_search_update_confidential_attrs(ac, data);
2798                 if (ret != LDB_SUCCESS) {
2799                         return ret;
2800                 }
2801
2802                 if (data->confidential_attrs != NULL) {
2803                         down_tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree);
2804                         if (down_tree == NULL) {
2805                                 return ldb_oom(ldb);
2806                         }
2807
2808                         for (i = 0; data->confidential_attrs[i]; i++) {
2809                                 ldb_parse_tree_attr_replace(down_tree,
2810                                                             data->confidential_attrs[i],
2811                                                             "kludgeACLredactedattribute");
2812                         }
2813                 }
2814         }
2815
2816         ret = ldb_build_search_req_ex(&down_req,
2817                                       ldb, ac,
2818                                       req->op.search.base,
2819                                       req->op.search.scope,
2820                                       down_tree,
2821                                       req->op.search.attrs,
2822                                       req->controls,
2823                                       ac, acl_search_callback,
2824                                       req);
2825         LDB_REQ_SET_LOCATION(down_req);
2826         if (ret != LDB_SUCCESS) {
2827                 return ret;
2828         }
2829         /* perform the search */
2830         return ldb_next_request(module, down_req);
2831 }
2832
2833 static int acl_extended(struct ldb_module *module, struct ldb_request *req)
2834 {
2835         struct ldb_context *ldb = ldb_module_get_ctx(module);
2836
2837         /* allow everybody to read the sequence number */
2838         if (strcmp(req->op.extended.oid,
2839                    LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
2840                 return ldb_next_request(module, req);
2841         }
2842
2843         if (dsdb_have_system_access(module,
2844                                     req,
2845                                     SYSTEM_CONTROL_KEEP_CRITICAL) ||
2846             dsdb_module_am_administrator(module))
2847         {
2848                 return ldb_next_request(module, req);
2849         } else {
2850                 ldb_asprintf_errstring(ldb,
2851                                        "acl_extended: "
2852                                        "attempted database modify not permitted. "
2853                                        "User %s is not SYSTEM or an administrator",
2854                                        acl_user_name(req, module));
2855                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2856         }
2857 }
2858
2859 static const struct ldb_module_ops ldb_acl_module_ops = {
2860         .name              = "acl",
2861         .search            = acl_search,
2862         .add               = acl_add,
2863         .modify            = acl_modify,
2864         .del               = acl_delete,
2865         .rename            = acl_rename,
2866         .extended          = acl_extended,
2867         .init_context      = acl_module_init
2868 };
2869
2870 int ldb_acl_module_init(const char *version)
2871 {
2872         LDB_MODULE_CHECK_VERSION(version);
2873         return ldb_register_module(&ldb_acl_module_ops);
2874 }