s4:dsdb/common/util.c - provide message set functions for integer types
[mat/samba.git] / source4 / dsdb / common / util.c
index f95cf91b8aff2287e98cc9624593f96c79ea642a..71215212fc0fcaf807fa99fabc72c4d2c7c914c9 100644 (file)
@@ -1101,6 +1101,37 @@ int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc
        return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
 }
 
+/*
+ * sets a signed integer in a message
+ */
+int samdb_msg_set_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
+                     struct ldb_message *msg, const char *attr_name, int v)
+{
+       struct ldb_message_element *el;
+
+       el = ldb_msg_find_element(msg, attr_name);
+       if (el) {
+               el->num_values = 0;
+       }
+       return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, v);
+}
+
+/*
+ * sets an unsigned integer in a message
+ */
+int samdb_msg_set_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
+                      struct ldb_message *msg, const char *attr_name,
+                      unsigned int v)
+{
+       struct ldb_message_element *el;
+
+       el = ldb_msg_find_element(msg, attr_name);
+       if (el) {
+               el->num_values = 0;
+       }
+       return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, v);
+}
+
 /*
  * Handle ldb_request in transaction
  */
@@ -1619,6 +1650,63 @@ struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
        return server_site_dn;
 }
 
+/*
+  find the site name from a computers DN record
+ */
+int samdb_find_site_for_computer(struct ldb_context *ldb,
+                                TALLOC_CTX *mem_ctx, struct ldb_dn *computer_dn,
+                                const char **site_name)
+{
+       int ret;
+       struct ldb_dn *dn;
+       const struct ldb_val *rdn_val;
+
+       *site_name = NULL;
+
+       ret = samdb_reference_dn(ldb, mem_ctx, computer_dn, "serverReferenceBL", &dn);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       if (!ldb_dn_remove_child_components(dn, 2)) {
+               talloc_free(dn);
+               return LDB_ERR_INVALID_DN_SYNTAX;
+       }
+       rdn_val = ldb_dn_get_rdn_val(dn);
+       (*site_name) = talloc_strndup(mem_ctx, (const char *)rdn_val->data, rdn_val->length);
+       talloc_free(dn);
+       if (!*site_name) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       return LDB_SUCCESS;
+}
+
+/*
+  find the NTDS GUID from a computers DN record
+ */
+int samdb_find_ntdsguid_for_computer(struct ldb_context *ldb, struct ldb_dn *computer_dn,
+                                    struct GUID *ntds_guid)
+{
+       int ret;
+       struct ldb_dn *dn;
+
+       *ntds_guid = GUID_zero();
+
+       ret = samdb_reference_dn(ldb, ldb, computer_dn, "serverReferenceBL", &dn);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
+               talloc_free(dn);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = dsdb_find_guid_by_dn(ldb, dn, ntds_guid);
+       talloc_free(dn);
+       return ret;
+}
+
 /*
   find a 'reference' DN that points at another object
   (eg. serverReference, rIDManagerReference etc)
@@ -1633,20 +1721,21 @@ int samdb_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_
        attrs[0] = attribute;
        attrs[1] = NULL;
 
-       ret = ldb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, NULL);
+       ret = dsdb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, DSDB_SEARCH_ONE_ONLY, NULL);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
-       if (res->count != 1) {
-               talloc_free(res);
-               return LDB_ERR_NO_SUCH_OBJECT;
-       }
 
        *dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], attribute);
        if (!*dn) {
+               if (!ldb_msg_find_element(res->msgs[0], attribute)) {
+                       ldb_asprintf_errstring(ldb, "Cannot find attribute %s of %s to calculate reference dn", attribute,
+                                              ldb_dn_get_linearized(base));
+               } else {
+                       ldb_asprintf_errstring(ldb, "Cannot interpret attribute %s of %s as a dn", attribute,
+                                              ldb_dn_get_linearized(base));
+               }
                talloc_free(res);
-               ldb_asprintf_errstring(ldb, "Cannot find dn of attribute %s of %s", attribute,
-                                       ldb_dn_get_linearized(base));
                return LDB_ERR_NO_SUCH_ATTRIBUTE;
        }
 
@@ -2458,7 +2547,9 @@ int dsdb_find_guid_attr_by_dn(struct ldb_context *ldb,
        attrs[0] = attribute;
        attrs[1] = NULL;
 
-       ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs, DSDB_SEARCH_SHOW_DELETED);
+       ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
+                            DSDB_SEARCH_SHOW_DELETED |
+                            DSDB_SEARCH_SHOW_RECYCLED);
        if (ret != LDB_SUCCESS) {
                talloc_free(tmp_ctx);
                return ret;
@@ -2532,7 +2623,9 @@ int dsdb_find_sid_by_dn(struct ldb_context *ldb,
 
        ZERO_STRUCTP(sid);
 
-       ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs, DSDB_SEARCH_SHOW_DELETED);
+       ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
+                            DSDB_SEARCH_SHOW_DELETED |
+                            DSDB_SEARCH_SHOW_RECYCLED);
        if (ret != LDB_SUCCESS) {
                talloc_free(tmp_ctx);
                return ret;
@@ -3001,7 +3094,8 @@ int dsdb_functional_level(struct ldb_context *ldb)
        int *domainFunctionality =
                talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int);
        if (!domainFunctionality) {
-               DEBUG(0,(__location__ ": WARNING: domainFunctionality not setup\n"));
+               /* this is expected during initial provision */
+               DEBUG(4,(__location__ ": WARNING: domainFunctionality not setup\n"));
                return DS_DOMAIN_FUNCTION_2000;
        }
        return *domainFunctionality;
@@ -3163,7 +3257,7 @@ uint32_t dsdb_dn_val_rmd_flags(const struct ldb_val *val)
        if (val->length < 13) {
                return 0;
        }
-       p = memmem(val->data, val->length-2, "<RMD_FLAGS=", 11);
+       p = memmem(val->data, val->length, "<RMD_FLAGS=", 11);
        if (!p) {
                return 0;
        }
@@ -3213,7 +3307,9 @@ int dsdb_wellknown_dn(struct ldb_context *samdb, TALLOC_CTX *mem_ctx,
                return ldb_operr(samdb);
        }
 
-       ret = dsdb_search_dn(samdb, tmp_ctx, &res, dn, attrs, DSDB_SEARCH_SHOW_DELETED);
+       ret = dsdb_search_dn(samdb, tmp_ctx, &res, dn, attrs,
+                            DSDB_SEARCH_SHOW_DELETED |
+                            DSDB_SEARCH_SHOW_RECYCLED);
        if (ret != LDB_SUCCESS) {
                talloc_free(tmp_ctx);
                return ret;
@@ -3511,6 +3607,13 @@ int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
                }
        }
 
+       if (dsdb_flags & DSDB_SEARCH_SHOW_RECYCLED) {
+               ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_RECYCLED_OID, false, NULL);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
        if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
                ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
                if (ret != LDB_SUCCESS) {
@@ -3700,6 +3803,32 @@ int dsdb_search_dn(struct ldb_context *ldb,
        return LDB_SUCCESS;
 }
 
+/*
+  search for attrs on one DN, by the GUID of the DN, allowing for
+  dsdb_flags controls
+ */
+int dsdb_search_by_dn_guid(struct ldb_context *ldb,
+                          TALLOC_CTX *mem_ctx,
+                          struct ldb_result **_res,
+                          const struct GUID *guid,
+                          const char * const *attrs,
+                          uint32_t dsdb_flags)
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       struct ldb_dn *dn;
+       int ret;
+
+       dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<GUID=%s>", GUID_string(tmp_ctx, guid));
+       if (!ldb_dn_validate(dn)) {
+               talloc_free(tmp_ctx);
+               return LDB_ERR_INVALID_DN_SYNTAX;
+       }
+
+       ret = dsdb_search_dn(ldb, mem_ctx, _res, dn, attrs, dsdb_flags);
+       talloc_free(tmp_ctx);
+       return ret;
+}
+
 /*
   general search with dsdb_flags for controls
  */
@@ -3753,6 +3882,7 @@ int dsdb_search(struct ldb_context *ldb,
        ret = dsdb_request_add_controls(req, dsdb_flags);
        if (ret != LDB_SUCCESS) {
                talloc_free(tmp_ctx);
+               ldb_reset_err_string(ldb);
                return ret;
        }
 
@@ -3769,10 +3899,12 @@ int dsdb_search(struct ldb_context *ldb,
        if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
                if (res->count == 0) {
                        talloc_free(tmp_ctx);
+                       ldb_reset_err_string(ldb);
                        return LDB_ERR_NO_SUCH_OBJECT;
                }
                if (res->count != 1) {
                        talloc_free(tmp_ctx);
+                       ldb_reset_err_string(ldb);
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
        }
@@ -4054,3 +4186,70 @@ WERROR dsdb_get_fsmo_role_info(TALLOC_CTX *tmp_ctx,
        }
        return WERR_OK;
 }
+
+const char *samdb_dn_to_dnshostname(struct ldb_context *ldb,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct ldb_dn *server_dn)
+{
+       int ldb_ret;
+       struct ldb_result *res = NULL;
+       const char * const attrs[] = { "dNSHostName", NULL};
+
+       ldb_ret = ldb_search(ldb, mem_ctx, &res,
+                            server_dn,
+                            LDB_SCOPE_BASE,
+                            attrs, NULL);
+       if (ldb_ret != LDB_SUCCESS) {
+               DEBUG(4, ("Failed to find dNSHostName for dn %s, ldb error: %s",
+                         ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
+               return NULL;
+       }
+
+       return samdb_result_string(res->msgs[0], "dNSHostName", NULL);
+}
+
+/*
+  returns true if an attribute is in the filter,
+  false otherwise, provided that attribute value is provided with the expression
+*/
+bool dsdb_attr_in_parse_tree(struct ldb_parse_tree *tree,
+                            const char *attr)
+{
+       unsigned int i;
+       switch (tree->operation) {
+       case LDB_OP_AND:
+       case LDB_OP_OR:
+               for (i=0;i<tree->u.list.num_elements;i++) {
+                       if (dsdb_attr_in_parse_tree(tree->u.list.elements[i],
+                                                       attr))
+                               return true;
+               }
+               return false;
+       case LDB_OP_NOT:
+               return dsdb_attr_in_parse_tree(tree->u.isnot.child, attr);
+       case LDB_OP_EQUALITY:
+       case LDB_OP_GREATER:
+       case LDB_OP_LESS:
+       case LDB_OP_APPROX:
+               if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
+                       return true;
+               }
+               return false;
+       case LDB_OP_SUBSTRING:
+               if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
+                       return true;
+               }
+               return false;
+       case LDB_OP_PRESENT:
+              /* (attrname=*) is not filtered out */
+               return false;
+       case LDB_OP_EXTENDED:
+               if (tree->u.extended.attr &&
+                   ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
+                      return true;
+               }
+               return false;
+       }
+       return false;
+}
+