r26227: Make loadparm_context part of a server task, move loadparm_contexts further...
[samba.git] / source4 / dsdb / samdb / samdb.c
index fdc78e3cad23576d7ed0af0b28f9d9f546f7a912..dd20937ab713e8fa7f31b802f9b942ae88c6b3bb 100644 (file)
 #include "libcli/ldap/ldap.h"
 #include "system/time.h"
 #include "system/filesys.h"
-#include "db_wrap.h"
+#include "ldb_wrap.h"
+#include "util/util_ldb.h"
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/common/flags.h"
+#include "param/param.h"
+
+char *samdb_relative_path(struct ldb_context *ldb,
+                                TALLOC_CTX *mem_ctx, 
+                                const char *name) 
+{
+       const char *base_url = 
+               (const char *)ldb_get_opaque(ldb, "ldb_url");
+       char *path, *p, *full_name;
+       if (name == NULL) {
+               return NULL;
+       }
+       if (name[0] == 0 || name[0] == '/' || strstr(name, ":/")) {
+               return talloc_strdup(mem_ctx, name);
+       }
+       path = talloc_strdup(mem_ctx, base_url);
+       if (path == NULL) {
+               return NULL;
+       }
+       if ( (p = strrchr(path, '/')) != NULL) {
+               p[0] = '\0';
+               full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
+       } else {
+               full_name = talloc_asprintf(mem_ctx, "./%s", name);
+       }
+       talloc_free(path);
+       return full_name;
+}
+
 
 /*
   connect to the SAM database
   return an opaque context pointer on success, or NULL on failure
  */
 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, 
+                                 struct loadparm_context *lp_ctx,
                                  struct auth_session_info *session_info)
 {
        struct ldb_context *ldb;
-       ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), session_info,
+       ldb = ldb_wrap_connect(mem_ctx, lp_ctx, 
+                              lp_sam_url(lp_ctx), session_info,
                               NULL, 0, NULL);
        if (!ldb) {
                return NULL;
@@ -386,7 +418,7 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_messa
 {
        const struct ldb_val *v;
        struct dom_sid *sid;
-       NTSTATUS status;
+       enum ndr_err_code ndr_err;
        v = ldb_msg_find_ldb_val(msg, attr);
        if (v == NULL) {
                return NULL;
@@ -395,9 +427,9 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_messa
        if (sid == NULL) {
                return NULL;
        }
-       status = ndr_pull_struct_blob(v, sid, sid, 
-                                     (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
-       if (!NT_STATUS_IS_OK(status)) {
+       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)) {
                talloc_free(sid);
                return NULL;
        }
@@ -410,7 +442,7 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_messa
 struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
 {
        const struct ldb_val *v;
-       NTSTATUS status;
+       enum ndr_err_code ndr_err;
        struct GUID guid;
        TALLOC_CTX *mem_ctx;
 
@@ -421,10 +453,10 @@ struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
 
        mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
        if (!mem_ctx) return guid;
-       status = ndr_pull_struct_blob(v, mem_ctx, &guid, 
-                                     (ndr_pull_flags_fn_t)ndr_pull_GUID);
+       ndr_err = ndr_pull_struct_blob(v, mem_ctx, &guid,
+                                      (ndr_pull_flags_fn_t)ndr_pull_GUID);
        talloc_free(mem_ctx);
-       if (!NT_STATUS_IS_OK(status)) {
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return guid;
        }
 
@@ -635,10 +667,6 @@ struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
 {
        int i;
        struct ldb_message_element *el = ldb_msg_find_element(msg, name);
-       struct ldb_val v;
-
-       v.data = discard_const_p(uint8_t, value);
-       v.length = strlen(value);
 
        if (!el) {
                return NULL;
@@ -684,21 +712,49 @@ int samdb_copy_template(struct ldb_context *ldb,
        struct ldb_result *res;
        struct ldb_message *t;
        int ret, i, j;
-       struct ldb_dn *basedn = ldb_dn_new(ldb, ldb, "cn=Templates");
+       struct ldb_context *templates_ldb;
+       char *templates_ldb_path; 
+       struct ldb_dn *basedn;
+
+       templates_ldb = talloc_get_type(ldb_get_opaque(ldb, "templates_ldb"), struct ldb_context);
+
+       if (!templates_ldb) {
+               templates_ldb_path = samdb_relative_path(ldb, 
+                                                       msg, 
+                                                       "templates.ldb");
+               if (!templates_ldb_path) {
+                       *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct path for template db");
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
 
+               templates_ldb = ldb_wrap_connect(ldb, global_loadparm, 
+                                               templates_ldb_path, NULL,
+                                               NULL, 0, NULL);
+               talloc_free(templates_ldb_path);
+               if (!templates_ldb) {
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+               
+               ret = ldb_set_opaque(ldb, "templates_ldb", templates_ldb);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
        *errstring = NULL;      
 
+       basedn = ldb_dn_new(templates_ldb, ldb, "cn=Templates");
        if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) {
+               talloc_free(basedn);
                *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'", 
                                             name);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        
        /* pull the template record */
-       ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, "cn=*", NULL, &res);
+       ret = ldb_search(templates_ldb, basedn, LDB_SCOPE_BASE, "(dn=*)", NULL, &res);  
        talloc_free(basedn);
        if (ret != LDB_SUCCESS) {
-               *errstring = talloc_steal(msg, ldb_errstring(ldb));
+               *errstring = talloc_steal(msg, ldb_errstring(templates_ldb));
                return ret;
        }
        if (res->count != 1) {
@@ -760,10 +816,11 @@ int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, stru
                         const char *attr_name, struct dom_sid *sid)
 {
        struct ldb_val v;
-       NTSTATUS status;
-       status = ndr_push_struct_blob(&v, mem_ctx, sid, 
-                                     (ndr_push_flags_fn_t)ndr_push_dom_sid);
-       if (!NT_STATUS_IS_OK(status)) {
+       enum ndr_err_code ndr_err;
+
+       ndr_err = ndr_push_struct_blob(&v, mem_ctx, sid,
+                                      (ndr_push_flags_fn_t)ndr_push_dom_sid);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return -1;
        }
        return ldb_msg_add_value(msg, attr_name, &v, NULL);
@@ -965,30 +1022,6 @@ 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);
 }
 
-/*
-  add a record
-*/
-int samdb_add(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
-{
-       return ldb_add(sam_ldb, msg);
-}
-
-/*
-  delete a record
-*/
-int samdb_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
-{
-       return ldb_delete(sam_ldb, dn);
-}
-
-/*
-  modify a record
-*/
-int samdb_modify(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
-{
-       return ldb_modify(sam_ldb, msg);
-}
-
 /*
   replace elements in a record
 */
@@ -1002,7 +1035,7 @@ int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_m
        }
 
        /* modify the samdb record */
-       return samdb_modify(sam_ldb, mem_ctx, msg);
+       return ldb_modify(sam_ldb, msg);
 }
 
 /*
@@ -1070,7 +1103,7 @@ const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
        struct dom_sid *domain_sid;
 
        /* see if we have a cached copy */
-       domain_sid = ldb_get_opaque(ldb, "cache.domain_sid");
+       domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
        if (domain_sid) {
                return domain_sid;
        }
@@ -1137,7 +1170,7 @@ struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
        struct ldb_dn *settings_dn;
        
        /* see if we have a cached copy */
-       settings_dn = ldb_get_opaque(ldb, "cache.settings_dn");
+       settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "cache.settings_dn");
        if (settings_dn) {
                return settings_dn;
        }
@@ -1190,7 +1223,7 @@ const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
        struct GUID *invocation_id;
        
        /* see if we have a cached copy */
-       invocation_id = ldb_get_opaque(ldb, "cache.invocation_id");
+       invocation_id = (struct GUID *)ldb_get_opaque(ldb, "cache.invocation_id");
        if (invocation_id) {
                return invocation_id;
        }
@@ -1240,7 +1273,8 @@ bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *in
        struct GUID *invocation_id_old;
 
        /* see if we have a cached copy */
-       invocation_id_old = ldb_get_opaque(ldb, "cache.invocation_id");
+       invocation_id_old = (struct GUID *)ldb_get_opaque(ldb, 
+                                                        "cache.invocation_id");
 
        tmp_ctx = talloc_new(ldb);
        if (tmp_ctx == NULL) {
@@ -1283,7 +1317,7 @@ const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
        struct GUID *ntds_guid;
        
        /* see if we have a cached copy */
-       ntds_guid = ldb_get_opaque(ldb, "cache.ntds_guid");
+       ntds_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
        if (ntds_guid) {
                return ntds_guid;
        }
@@ -1333,7 +1367,7 @@ bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_
        struct GUID *ntds_guid_old;
        
        /* see if we have a cached copy */
-       ntds_guid_old = ldb_get_opaque(ldb, "cache.ntds_guid");
+       ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
 
        tmp_ctx = talloc_new(ldb);
        if (tmp_ctx == NULL) {
@@ -1392,19 +1426,19 @@ struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
 /*
   work out if we are the PDC for the domain of the current open ldb
 */
-BOOL samdb_is_pdc(struct ldb_context *ldb)
+bool samdb_is_pdc(struct ldb_context *ldb)
 {
        const char *dom_attrs[] = { "fSMORoleOwner", NULL };
        int ret;
        struct ldb_result *dom_res;
        TALLOC_CTX *tmp_ctx;
-       BOOL is_pdc;
+       bool is_pdc;
        struct ldb_dn *pdc;
 
        tmp_ctx = talloc_new(ldb);
        if (tmp_ctx == NULL) {
                DEBUG(1, ("talloc_new failed in samdb_is_pdc"));
-               return False;
+               return false;
        }
 
        ret = ldb_search(ldb, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
@@ -1422,9 +1456,9 @@ BOOL samdb_is_pdc(struct ldb_context *ldb)
        pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0], "fSMORoleOwner");
 
        if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc) == 0) {
-               is_pdc = True;
+               is_pdc = true;
        } else {
-               is_pdc = False;
+               is_pdc = false;
        }
 
        talloc_free(tmp_ctx);
@@ -1434,12 +1468,13 @@ BOOL samdb_is_pdc(struct ldb_context *ldb)
 failed:
        DEBUG(1,("Failed to find if we are the PDC for this ldb\n"));
        talloc_free(tmp_ctx);
-       return False;
+       return false;
 }
 
 
 /* Find a domain object in the parents of a particular DN.  */
-struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
+int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
+                                  struct ldb_dn **parent_dn, const char **errstring)
 {
        TALLOC_CTX *local_ctx;
        struct ldb_dn *sdn = dn;
@@ -1448,7 +1483,7 @@ struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CT
        const char *attrs[] = { NULL };
 
        local_ctx = talloc_new(mem_ctx);
-       if (local_ctx == NULL) return NULL;
+       if (local_ctx == NULL) return LDB_ERR_OPERATIONS_ERROR;
        
        while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
                ret = ldb_search(ldb, sdn, LDB_SCOPE_BASE, 
@@ -1458,24 +1493,35 @@ struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CT
                        if (res->count == 1) {
                                break;
                        }
+               } else {
+                       break;
                }
        }
 
-       if (ret != LDB_SUCCESS || res->count != 1) {
+       if (ret != LDB_SUCCESS) {
+               *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
+                                            ldb_dn_get_linearized(dn),
+                                            ldb_dn_get_linearized(sdn),
+                                            ldb_errstring(ldb));
                talloc_free(local_ctx);
-               return NULL;
+               return ret;
+       }
+       if (res->count != 1) {
+               *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
+                                            ldb_dn_get_linearized(dn));
+               talloc_free(local_ctx);
+               return LDB_ERR_CONSTRAINT_VIOLATION;
        }
 
-       talloc_steal(mem_ctx, sdn);
+       *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
        talloc_free(local_ctx);
-
-       return sdn;
+       return ret;
 }
 
 /*
   check that a password is sufficiently complex
 */
-static BOOL samdb_password_complexity_ok(const char *pass)
+static bool samdb_password_complexity_ok(const char *pass)
 {
        return check_password_quality(pass);
 }
@@ -1501,7 +1547,7 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
                            const char *new_pass,
                            struct samr_Password *lmNewHash, 
                            struct samr_Password *ntNewHash,
-                           BOOL user_change,
+                           bool user_change,
                            enum samr_RejectReason *reject_reason,
                            struct samr_DomInfo1 **_dominfo)
 {
@@ -1522,7 +1568,7 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
        int sambaLMPwdHistory_len, sambaNTPwdHistory_len;
        struct dom_sid *domain_sid;
        struct ldb_message **res;
-       BOOL restrictions;
+       bool restrictions;
        int count;
        time_t now = time(NULL);
        NTTIME now_nt;
@@ -1739,7 +1785,7 @@ _PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *me
                                const char *new_pass,
                                struct samr_Password *lmNewHash, 
                                struct samr_Password *ntNewHash,
-                               BOOL user_change,
+                               bool user_change,
                                enum samr_RejectReason *reject_reason,
                                struct samr_DomInfo1 **_dominfo) 
 {
@@ -1812,7 +1858,7 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
                               struct dom_sid *group_sid, 
                               int n_groupSIDs,
                               struct dom_sid **groupSIDs, 
-                              BOOL is_authenticated,
+                              bool is_authenticated,
                               struct security_token **token)
 {
        struct security_token *ptoken;
@@ -1923,7 +1969,7 @@ NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TA
                             "foreignSecurityPrincipal");
        
        /* create the alias */
-       ret = samdb_add(sam_ctx, mem_ctx, msg);
+       ret = ldb_add(sam_ctx, msg);
        if (ret != 0) {
                DEBUG(0,("Failed to create foreignSecurityPrincipal "
                         "record %s: %s\n",