build: moved libds/common/flag_mapping.c into a common subsystem
[kai/samba.git] / source4 / dsdb / common / util.c
index f56cd07f3a34c1ac6dfab6b8e226d63a90306897..e711a324f8a3cd1d5102e7b6b29ec5d900c07e76 100644 (file)
@@ -43,6 +43,7 @@
 #include "dsdb/common/util.h"
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/irpc.h"
+#include "libds/common/flag_mapping.h"
 
 /*
   search the sam for the specified attributes in a specific domain, filter on
@@ -192,19 +193,17 @@ struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
   return the count of the number of records in the sam matching the query
 */
 int samdb_search_count(struct ldb_context *sam_ldb,
+                      TALLOC_CTX *mem_ctx,
                       struct ldb_dn *basedn,
-                      const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
+                      const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
 {
        va_list ap;
-       struct ldb_message **res;
        const char *attrs[] = { NULL };
        int ret;
-       TALLOC_CTX *tmp_ctx = talloc_new(sam_ldb);
 
        va_start(ap, format);
-       ret = gendb_search_v(sam_ldb, tmp_ctx, basedn, &res, attrs, format, ap);
+       ret = gendb_search_v(sam_ldb, mem_ctx, basedn, NULL, attrs, format, ap);
        va_end(ap);
-       talloc_free(tmp_ctx);
 
        return ret;
 }
@@ -350,9 +349,9 @@ uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message
 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
                                     const char *attr)
 {
+       bool ok;
        const struct ldb_val *v;
        struct dom_sid *sid;
-       enum ndr_err_code ndr_err;
        v = ldb_msg_find_ldb_val(msg, attr);
        if (v == NULL) {
                return NULL;
@@ -361,9 +360,8 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_messa
        if (sid == NULL) {
                return NULL;
        }
-       ndr_err = ndr_pull_struct_blob(v, sid, sid,
-                                      (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+       ok = sid_blob_parse(*v, sid);
+       if (!ok) {
                talloc_free(sid);
                return NULL;
        }
@@ -701,47 +699,6 @@ struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
        return NULL;
 }
 
-/*
- * This is intended for use by the "password hash" module since there
- * password changes can be specified through one message element with the
- * new password (to set) and another one with the old password (to unset).
- *
- * The first which sets a password (new value) can have flags
- * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
- * for entries). The latter (old value) has always specified
- * LDB_FLAG_MOD_DELETE.
- *
- * Returns LDB_ERR_NO_SUCH_ATTRIBUTE if the attribute which should be deleted
- * doesn't contain only one value (this is the Windows Server behaviour)
- * otherwise LDB_SUCCESS.
- */
-int samdb_msg_find_old_and_new_ldb_val(const struct ldb_message *msg,
-                                      const char *name,
-                                      const struct ldb_val **new_val,
-                                      const struct ldb_val **old_val)
-{
-       unsigned int i;
-
-       *new_val = NULL;
-       *old_val = NULL;
-
-       if (msg == NULL) {
-               return LDB_SUCCESS;
-       }
-
-       for (i = 0; i < msg->num_elements; i++) {
-               if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
-                       if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE) {
-                               *old_val = &msg->elements[i].values[0];
-                       } else {
-                               *new_val = &msg->elements[i].values[0];
-                       }
-               }
-       }
-
-       return LDB_SUCCESS;
-}
-
 int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
 {
        if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
@@ -851,7 +808,7 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
                }
        }
 
-       vals = talloc_realloc(msg, el->values, struct ldb_val,
+       vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
                              el->num_values + 1);
        if (vals == NULL) {
                return ldb_oom(sam_ldb);
@@ -907,7 +864,7 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
                }
        }
 
-       vals = talloc_realloc(msg, el->values, struct ldb_val,
+       vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
                              el->num_values + 1);
        if (vals == NULL) {
                return ldb_oom(sam_ldb);
@@ -1349,28 +1306,6 @@ failed:
        return false;
 }
 
-/* Obtain the short name of the flexible single master operator
- * (FSMO), such as the PDC Emulator */
-const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
-                            const char *attr)
-{
-       /* Format is cn=NTDS Settings,cn=<NETBIOS name of FSMO>,.... */
-       struct ldb_dn *fsmo_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
-       const struct ldb_val *val = ldb_dn_get_component_val(fsmo_dn, 1);
-       const char *name = ldb_dn_get_component_name(fsmo_dn, 1);
-
-       if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
-               /* Ensure this matches the format.  This gives us a
-                * bit more confidence that a 'cn' value will be a
-                * ascii string */
-               return NULL;
-       }
-       if (val) {
-               return (char *)val->data;
-       }
-       return NULL;
-}
-
 /*
   work out the ntds settings dn for the current open ldb
 */
@@ -1407,7 +1342,7 @@ struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
        settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
 
        /* cache the domain_sid in the ldb */
-       if (ldb_set_opaque(ldb, "cache.settings_dn", settings_dn) != LDB_SUCCESS) {
+       if (ldb_set_opaque(ldb, "cache.ntds_settings_dn", settings_dn) != LDB_SUCCESS) {
                goto failed;
        }
 
@@ -1660,7 +1595,12 @@ int samdb_find_site_for_computer(struct ldb_context *ldb,
                talloc_free(dn);
                return LDB_ERR_INVALID_DN_SYNTAX;
        }
+
        rdn_val = ldb_dn_get_rdn_val(dn);
+       if (rdn_val == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        (*site_name) = talloc_strndup(mem_ctx, (const char *)rdn_val->data, rdn_val->length);
        talloc_free(dn);
        if (!*site_name) {
@@ -1871,7 +1811,7 @@ const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
                 * is for sure the same as our server site). If more sites do
                 * exist then we don't know which one to use and set the site
                 * name to "". */
-               cnt = samdb_search_count(ldb, sites_container_dn,
+               cnt = samdb_search_count(ldb, mem_ctx, sites_container_dn,
                                         "(objectClass=site)");
                if (cnt == 1) {
                        site_name = samdb_server_site_name(ldb, mem_ctx);
@@ -3342,15 +3282,41 @@ int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb
                DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
                talloc_free(tmp_ctx);
                return ret;
-       }
+       }
 
-       el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
-       if (!el) {
-               DEBUG(1,("Finding namingContexts element in root_res failed: %s\n",
-                       ldb_errstring(samdb)));
-              talloc_free(tmp_ctx);
-              return LDB_ERR_NO_SUCH_ATTRIBUTE;
-       }
+       el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
+       if ((el == NULL) || (el->num_values < 3)) {
+               struct ldb_message *tmp_msg;
+
+               DEBUG(5,("dsdb_find_nc_root: Finding a valid 'namingContexts' element in the RootDSE failed. Using a temporary list."));
+
+               /* This generates a temporary list of NCs in order to let the
+                * provisioning work. */
+               tmp_msg = ldb_msg_new(tmp_ctx);
+               if (tmp_msg == NULL) {
+                       talloc_free(tmp_ctx);
+                       return ldb_oom(samdb);
+               }
+               ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
+                                              ldb_dn_alloc_linearized(tmp_msg, ldb_get_schema_basedn(samdb)));
+               if (ret != LDB_SUCCESS) {
+                       talloc_free(tmp_ctx);
+                       return ret;
+               }
+               ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
+                                              ldb_dn_alloc_linearized(tmp_msg, ldb_get_config_basedn(samdb)));
+               if (ret != LDB_SUCCESS) {
+                       talloc_free(tmp_ctx);
+                       return ret;
+               }
+               ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
+                                              ldb_dn_alloc_linearized(tmp_msg, ldb_get_default_basedn(samdb)));
+               if (ret != LDB_SUCCESS) {
+                       talloc_free(tmp_ctx);
+                       return ret;
+               }
+               el = &tmp_msg->elements[0];
+       }
 
        nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
        if (!nc_dns) {
@@ -3660,6 +3626,13 @@ int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
                }
        }
 
+       if (dsdb_flags & DSDB_PROVISION) {
+               ret = ldb_request_add_control(req, LDB_CONTROL_PROVISION_OID, false, NULL);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
        return LDB_SUCCESS;
 }
 
@@ -3980,6 +3953,25 @@ const char *samdb_forest_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
        return forest_name;
 }
 
+/* returns back the default domain DNS name */
+const char *samdb_default_domain_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
+{
+       const char *domain_name = ldb_dn_canonical_string(mem_ctx,
+                                                         ldb_get_default_basedn(ldb));
+       char *p;
+
+       if (domain_name == NULL) {
+               return NULL;
+       }
+
+       p = strchr(domain_name, '/');
+       if (p) {
+               *p = '\0';
+       }
+
+       return domain_name;
+}
+
 /*
    validate that an DSA GUID belongs to the specified user sid.
    The user SID must be a domain controller account (either RODC or
@@ -4066,18 +4058,8 @@ int dsdb_validate_dsa_guid(struct ldb_context *ldb,
        return LDB_SUCCESS;
 }
 
-static const char *secret_attributes[] = {
-       "currentValue",
-       "dBCSPwd",
-       "initialAuthIncoming",
-       "initialAuthOutgoing",
-       "lmPwdHistory",
-       "ntPwdHistory",
-       "priorValue",
-       "supplementalCredentials",
-       "trustAuthIncoming",
-       "trustAuthOutgoing",
-       "unicodePwd",
+static const char * const secret_attributes[] = {
+       DSDB_SECRET_ATTRIBUTES,
        NULL
 };