r10914: moved the ldap time string functions into ldb so they can be used by
[kamenim/samba.git] / source4 / dsdb / samdb / samdb.c
index 81ce05d9fe88e356012437541c307af7a2763181..2e1ce9ecb5beb59f232de3a8f82637f05d755346 100644 (file)
 
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_netlogon.h"
+#include "librpc/gen_ndr/ndr_misc.h"
 #include "lib/ldb/include/ldb.h"
 #include "system/time.h"
+#include "system/filesys.h"
+#include "db_wrap.h"
 
 /*
   connect to the SAM database
   return an opaque context pointer on success, or NULL on failure
  */
-struct ldb_wrap *samdb_connect(TALLOC_CTX *mem_ctx)
+struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, struct auth_session_info *session_info)
 {
-       return ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL);
-}
-
-/*
-  search the sam for the specified attributes - varargs variant
-*/
-int samdb_search(struct ldb_wrap *sam_ctx,
-                TALLOC_CTX *mem_ctx, 
-                const char *basedn,
-                struct ldb_message ***res,
-                const char * const *attrs,
-                const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
-{
-       va_list ap;
-       int count;
-
-       va_start(ap, format);
-       count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, res, attrs, format, ap);
-       va_end(ap);
-
-       return count;
+       struct ldb_context *ldb;
+       ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL);
+       if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
+               return NULL;
+       }
+       return ldb;
 }
 
 /*
   search the sam for the specified attributes in a specific domain, filter on
   objectSid being in domain_sid.
 */
-int samdb_search_domain(struct ldb_wrap *sam_ctx,
+int samdb_search_domain(struct ldb_context *sam_ldb,
                        TALLOC_CTX *mem_ctx, 
-                       const char *basedn,
+                       const struct ldb_dn *basedn,
                        struct ldb_message ***res,
                        const char * const *attrs,
                        const struct dom_sid *domain_sid,
@@ -70,8 +58,8 @@ int samdb_search_domain(struct ldb_wrap *sam_ctx,
        int i, count;
 
        va_start(ap, format);
-       count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, res, attrs,
-                              format, ap);
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn,
+                              res, attrs, format, ap);
        va_end(ap);
 
        i=0;
@@ -79,52 +67,45 @@ int samdb_search_domain(struct ldb_wrap *sam_ctx,
        while (i<count) {
                struct dom_sid *entry_sid;
 
-               entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i],
-                                                "objectSid");
+               entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
 
                if ((entry_sid == NULL) ||
                    (!dom_sid_in_domain(domain_sid, entry_sid))) {
-
                        /* Delete that entry from the result set */
                        (*res)[i] = (*res)[count-1];
                        count -= 1;
+                       talloc_free(entry_sid);
                        continue;
                }
+               talloc_free(entry_sid);
                i += 1;
        }
 
        return count;
 }
 
-/*
-  free up a search result
-*/
-int samdb_search_free(struct ldb_wrap *sam_ctx,
-                     TALLOC_CTX *mem_ctx, struct ldb_message **res)
-{
-       return ldb_search_free(sam_ctx->ldb, res);
-}
-
 /*
   search the sam for a single string attribute in exactly 1 record
 */
-const char *samdb_search_string_v(struct ldb_wrap *sam_ctx,
+const char *samdb_search_string_v(struct ldb_context *sam_ldb,
                                  TALLOC_CTX *mem_ctx,
-                                 const char *basedn,
+                                 const struct ldb_dn *basedn,
                                  const char *attr_name,
                                  const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
 {
        int count;
-       const char * const attrs[2] = { attr_name, NULL };
+       const char *attrs[2] = { NULL, NULL };
        struct ldb_message **res = NULL;
 
-       count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
+       attrs[0] = attr_name;
+
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
        if (count > 1) {                
                DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n", 
                         attr_name, format, count));
        }
        if (count != 1) {
-               samdb_search_free(sam_ctx, mem_ctx, res);
+               talloc_free(res);
                return NULL;
        }
 
@@ -135,9 +116,9 @@ const char *samdb_search_string_v(struct ldb_wrap *sam_ctx,
 /*
   search the sam for a single string attribute in exactly 1 record
 */
-const char *samdb_search_string(struct ldb_wrap *sam_ctx,
+const char *samdb_search_string(struct ldb_context *sam_ldb,
                                TALLOC_CTX *mem_ctx,
-                               const char *basedn,
+                               const struct ldb_dn *basedn,
                                const char *attr_name,
                                const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
 {
@@ -145,18 +126,73 @@ const char *samdb_search_string(struct ldb_wrap *sam_ctx,
        const char *str;
 
        va_start(ap, format);
-       str = samdb_search_string_v(sam_ctx, mem_ctx, basedn, attr_name, format, ap);
+       str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
        va_end(ap);
 
        return str;
 }
 
+struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
+                              TALLOC_CTX *mem_ctx,
+                              const struct ldb_dn *basedn,
+                              const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
+{
+       va_list ap;
+       struct ldb_dn *ret;
+       struct ldb_message **res = NULL;
+       int count;
+
+       va_start(ap, format);
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
+       va_end(ap);
+
+       if (count != 1) return NULL;
+
+       ret = talloc_steal(mem_ctx, res[0]->dn);
+       talloc_free(res);
+
+       return ret;
+}
+
+/*
+  search the sam for a dom_sid attribute in exactly 1 record
+*/
+struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
+                                    TALLOC_CTX *mem_ctx,
+                                    const struct ldb_dn *basedn,
+                                    const char *attr_name,
+                                    const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
+{
+       va_list ap;
+       int count;
+       struct ldb_message **res;
+       const char *attrs[2] = { NULL, NULL };
+       struct dom_sid *sid;
+
+       attrs[0] = attr_name;
+
+       va_start(ap, format);
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+       va_end(ap);
+       if (count > 1) {                
+               DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n", 
+                        attr_name, format, count));
+       }
+       if (count != 1) {
+               talloc_free(res);
+               return NULL;
+       }
+       sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
+       talloc_free(res);
+       return sid;     
+}
+
 /*
   return the count of the number of records in the sam matching the query
 */
-int samdb_search_count(struct ldb_wrap *sam_ctx,
+int samdb_search_count(struct ldb_context *sam_ldb,
                       TALLOC_CTX *mem_ctx,
-                      const char *basedn,
+                      const struct ldb_dn *basedn,
                       const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
 {
        va_list ap;
@@ -165,7 +201,7 @@ int samdb_search_count(struct ldb_wrap *sam_ctx,
        int ret;
 
        va_start(ap, format);
-       ret = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
+       ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
        va_end(ap);
 
        return ret;
@@ -175,20 +211,22 @@ int samdb_search_count(struct ldb_wrap *sam_ctx,
 /*
   search the sam for a single integer attribute in exactly 1 record
 */
-uint_t samdb_search_uint(struct ldb_wrap *sam_ctx,
+uint_t samdb_search_uint(struct ldb_context *sam_ldb,
                         TALLOC_CTX *mem_ctx,
                         uint_t default_value,
-                        const char *basedn,
+                        const struct ldb_dn *basedn,
                         const char *attr_name,
                         const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
 {
        va_list ap;
        int count;
        struct ldb_message **res;
-       const char * const attrs[2] = { attr_name, NULL };
+       const char *attrs[2] = { NULL, NULL };
+
+       attrs[0] = attr_name;
 
        va_start(ap, format);
-       count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
        va_end(ap);
 
        if (count != 1) {
@@ -201,20 +239,22 @@ uint_t samdb_search_uint(struct ldb_wrap *sam_ctx,
 /*
   search the sam for a single signed 64 bit integer attribute in exactly 1 record
 */
-int64_t samdb_search_int64(struct ldb_wrap *sam_ctx,
+int64_t samdb_search_int64(struct ldb_context *sam_ldb,
                           TALLOC_CTX *mem_ctx,
                           int64_t default_value,
-                          const char *basedn,
+                          const struct ldb_dn *basedn,
                           const char *attr_name,
                           const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
 {
        va_list ap;
        int count;
        struct ldb_message **res;
-       const char * const attrs[2] = { attr_name, NULL };
+       const char *attrs[2] = { NULL, NULL };
+
+       attrs[0] = attr_name;
 
        va_start(ap, format);
-       count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
        va_end(ap);
 
        if (count != 1) {
@@ -228,20 +268,22 @@ int64_t samdb_search_int64(struct ldb_wrap *sam_ctx,
   search the sam for multipe records each giving a single string attribute
   return the number of matches, or -1 on error
 */
-int samdb_search_string_multiple(struct ldb_wrap *sam_ctx,
+int samdb_search_string_multiple(struct ldb_context *sam_ldb,
                                 TALLOC_CTX *mem_ctx,
-                                const char *basedn,
+                                const struct ldb_dn *basedn,
                                 const char ***strs,
                                 const char *attr_name,
                                 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
 {
        va_list ap;
        int count, i;
-       const char * const attrs[2] = { attr_name, NULL };
+       const char *attrs[2] = { NULL, NULL };
        struct ldb_message **res = NULL;
 
+       attrs[0] = attr_name;
+
        va_start(ap, format);
-       count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
+       count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
        va_end(ap);
 
        if (count <= 0) {
@@ -253,14 +295,14 @@ int samdb_search_string_multiple(struct ldb_wrap *sam_ctx,
                if (res[i]->num_elements != 1) {
                        DEBUG(1,("samdb: search for %s %s not single valued\n", 
                                 attr_name, format));
-                       samdb_search_free(sam_ctx, mem_ctx, res);
+                       talloc_free(res);
                        return -1;
                }
        }
 
-       *strs = talloc_array_p(mem_ctx, const char *, count+1);
+       *strs = talloc_array(mem_ctx, const char *, count+1);
        if (! *strs) {
-               samdb_search_free(sam_ctx, mem_ctx, res);
+               talloc_free(res);
                return -1;
        }
 
@@ -297,20 +339,30 @@ const char *samdb_result_string(struct ldb_message *msg, const char *attr,
        return ldb_msg_find_string(msg, attr, default_value);
 }
 
+struct ldb_dn *samdb_result_dn(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+                              const char *attr, struct ldb_dn *default_value)
+{
+       const char *string = samdb_result_string(msg, attr, NULL);
+       if (string == NULL) return default_value;
+       return ldb_dn_explode(mem_ctx, string);
+}
+
 /*
   pull a rid from a objectSid in a result set. 
 */
 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg, 
-                                const char *attr, uint32_t default_value)
+                                  const char *attr, uint32_t default_value)
 {
        struct dom_sid *sid;
-       const char *sidstr = ldb_msg_find_string(msg, attr, NULL);
-       if (!sidstr) return default_value;
-
-       sid = dom_sid_parse_talloc(mem_ctx, sidstr);
-       if (!sid) return default_value;
+       uint32_t rid;
 
-       return sid->sub_auths[sid->num_auths-1];
+       sid = samdb_result_dom_sid(mem_ctx, msg, attr);
+       if (sid == NULL) {
+               return default_value;
+       }
+       rid = sid->sub_auths[sid->num_auths-1];
+       talloc_free(sid);
+       return rid;
 }
 
 /*
@@ -319,10 +371,24 @@ uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg, 
                                     const char *attr)
 {
-       const char *sidstr = ldb_msg_find_string(msg, attr, NULL);
-       if (!sidstr) return NULL;
-
-       return dom_sid_parse_talloc(mem_ctx, sidstr);
+       const struct ldb_val *v;
+       struct dom_sid *sid;
+       NTSTATUS status;
+       v = ldb_msg_find_ldb_val(msg, attr);
+       if (v == NULL) {
+               return NULL;
+       }
+       sid = talloc(mem_ctx, struct dom_sid);
+       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)) {
+               talloc_free(sid);
+               return NULL;
+       }
+       return sid;
 }
 
 /*
@@ -330,17 +396,22 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *ms
 */
 struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
 {
+       const struct ldb_val *v;
        NTSTATUS status;
        struct GUID guid;
-       const char *guidstr = ldb_msg_find_string(msg, attr, NULL);
+       TALLOC_CTX *mem_ctx;
 
        ZERO_STRUCT(guid);
 
-       if (!guidstr) return guid;
+       v = ldb_msg_find_ldb_val(msg, attr);
+       if (!v) return guid;
 
-       status = GUID_from_string(guidstr, &guid);
+       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);
+       talloc_free(mem_ctx);
        if (!NT_STATUS_IS_OK(status)) {
-               ZERO_STRUCT(guid);
                return guid;
        }
 
@@ -351,23 +422,22 @@ struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
   pull a sid prefix from a objectSid in a result set. 
   this is used to find the domain sid for a user
 */
-const char *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg, 
-                                   const char *attr)
+struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg, 
+                                       const char *attr)
 {
        struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
        if (!sid || sid->num_auths < 1) return NULL;
-
        sid->num_auths--;
-
-       return dom_sid_string(mem_ctx, sid);
+       return sid;
 }
 
 /*
   pull a NTTIME in a result set. 
 */
-NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, const char *default_value)
+NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME default_value)
 {
-       const char *str = ldb_msg_find_string(msg, attr, default_value);
+       const char *str = ldb_msg_find_string(msg, attr, NULL);
+       if (!str) return default_value;
        return nttime_from_string(str);
 }
 
@@ -384,9 +454,9 @@ uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t
   construct the allow_password_change field from the PwdLastSet attribute and the 
   domain password settings
 */
-NTTIME samdb_result_allow_password_change(struct ldb_wrap *sam_ctx
+NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb
                                          TALLOC_CTX *mem_ctx, 
-                                         const char *domain_dn, 
+                                         const struct ldb_dn *domain_dn, 
                                          struct ldb_message *msg, 
                                          const char *attr)
 {
@@ -397,8 +467,7 @@ NTTIME samdb_result_allow_password_change(struct ldb_wrap *sam_ctx,
                return 0;
        }
 
-       minPwdAge = samdb_search_int64(sam_ctx, mem_ctx, 0, NULL, 
-                                      "minPwdAge", "dn=%s", domain_dn);
+       minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
 
        /* yes, this is a -= not a += as minPwdAge is stored as the negative
           of the number of 100-nano-seconds */
@@ -411,9 +480,9 @@ NTTIME samdb_result_allow_password_change(struct ldb_wrap *sam_ctx,
   construct the force_password_change field from the PwdLastSet attribute and the 
   domain password settings
 */
-NTTIME samdb_result_force_password_change(struct ldb_wrap *sam_ctx
+NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb
                                          TALLOC_CTX *mem_ctx, 
-                                         const char *domain_dn, 
+                                         const struct ldb_dn *domain_dn, 
                                          struct ldb_message *msg, 
                                          const char *attr)
 {
@@ -424,7 +493,7 @@ NTTIME samdb_result_force_password_change(struct ldb_wrap *sam_ctx,
                return 0;
        }
 
-       maxPwdAge = samdb_search_int64(sam_ctx, mem_ctx, 0, NULL, "maxPwdAge", "dn=%s", domain_dn);
+       maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
        if (maxPwdAge == 0) {
                return 0;
        } else {
@@ -467,7 +536,7 @@ uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                return 0;
        }
 
-       *hashes = talloc_array_p(mem_ctx, struct samr_Password, count);
+       *hashes = talloc_array(mem_ctx, struct samr_Password, count);
        if (! *hashes) {
                return 0;
        }
@@ -488,7 +557,7 @@ NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
        struct samr_Password *lmPwdHash, *ntPwdHash;
        if (unicodePwd) {
                if (nt_pwd) {
-                       ntPwdHash = talloc_p(mem_ctx, struct samr_Password);
+                       ntPwdHash = talloc(mem_ctx, struct samr_Password);
                        if (!ntPwdHash) {
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -500,7 +569,7 @@ NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                if (lm_pwd) {
                        BOOL lm_hash_ok;
                
-                       lmPwdHash = talloc_p(mem_ctx, struct samr_Password);
+                       lmPwdHash = talloc(mem_ctx, struct samr_Password);
                        if (!lmPwdHash) {
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -551,7 +620,7 @@ struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_
        const int units_per_week = 168;
        const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
        ZERO_STRUCT(hours);
-       hours.bits = talloc_array_p(mem_ctx, uint8, units_per_week);
+       hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
        if (!hours.bits) {
                return hours;
        }
@@ -575,7 +644,7 @@ uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
 /*
   copy from a template record to a message
 */
-int samdb_copy_template(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, 
+int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, 
                        struct ldb_message *msg, const char *expression)
 {
        struct ldb_message **res, *t;
@@ -583,7 +652,7 @@ int samdb_copy_template(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx,
        
 
        /* pull the template record */
-       ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, NULL, "%s", expression);
+       ret = gendb_search(sam_ldb, mem_ctx, NULL, &res, NULL, "%s", expression);
        if (ret != 1) {
                DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n", 
                         expression, ret));
@@ -610,7 +679,7 @@ int samdb_copy_template(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx,
                             strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
                                continue;
                        }
-                       samdb_msg_add_string(sam_ctx, mem_ctx, msg, el->name, 
+                       samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name, 
                                             (char *)el->values[j].data);
                }
        }
@@ -620,120 +689,40 @@ int samdb_copy_template(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx,
 
 
 /*
-  allocate a new id, attempting to do it atomically
-  return 0 on failure, the id on success
+  add a string element to a message
 */
-static NTSTATUS _samdb_allocate_next_id(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, const char *dn, 
-                                       const char *attr, uint32_t *id)
+int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+                        const char *attr_name, const char *str)
 {
-       struct ldb_message msg;
-       int ret;
-       const char *str;
-       struct ldb_val vals[2];
-       struct ldb_message_element els[2];
-
-       str = samdb_search_string(sam_ctx, mem_ctx, NULL, attr, "dn=%s", dn);
-       if (!str) {
-               DEBUG(1,("id not found at %s %s\n", dn, attr));
-               return NT_STATUS_OBJECT_NAME_INVALID;
-       }
-
-       *id = strtol(str, NULL, 0);
-       if ((*id)+1 == 0) {
-               /* out of IDs ! */
-               return NT_STATUS_INSUFFICIENT_RESOURCES;
-       }
-
-       /* we do a delete and add as a single operation. That prevents
-          a race */
-       ZERO_STRUCT(msg);
-       msg.dn = talloc_strdup(mem_ctx, dn);
-       if (!msg.dn) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       msg.num_elements = 2;
-       msg.elements = els;
-
-       els[0].num_values = 1;
-       els[0].values = &vals[0];
-       els[0].flags = LDB_FLAG_MOD_DELETE;
-       els[0].name = talloc_strdup(mem_ctx, attr);
-       if (!els[0].name) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       els[1].num_values = 1;
-       els[1].values = &vals[1];
-       els[1].flags = LDB_FLAG_MOD_ADD;
-       els[1].name = els[0].name;
-
-       vals[0].data = talloc_asprintf(mem_ctx, "%u", *id);
-       if (!vals[0].data) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       vals[0].length = strlen(vals[0].data);
-
-       vals[1].data = talloc_asprintf(mem_ctx, "%u", (*id)+1);
-       if (!vals[1].data) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       vals[1].length = strlen(vals[1].data);
-
-       ret = ldb_modify(sam_ctx->ldb, &msg);
-       if (ret != 0) {
-               return NT_STATUS_UNEXPECTED_IO_ERROR;
+       char *s = talloc_strdup(mem_ctx, str);
+       char *a = talloc_strdup(mem_ctx, attr_name);
+       if (s == NULL || a == NULL) {
+               return -1;
        }
-
-       (*id)++;
-
-       return NT_STATUS_OK;
+       return ldb_msg_add_string(msg, a, s);
 }
 
 /*
-  allocate a new id, attempting to do it atomically
-  return 0 on failure, the id on success
+  add a dom_sid element to a message
 */
-NTSTATUS samdb_allocate_next_id(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, const char *dn, const char *attr,
-                               uint32_t *id)
+int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+                        const char *attr_name, struct dom_sid *sid)
 {
-       int tries = 10;
+       struct ldb_val v;
        NTSTATUS status;
-
-       /* we need to try multiple times to cope with two account
-          creations at the same time */
-       while (tries--) {
-               status = _samdb_allocate_next_id(sam_ctx, mem_ctx, dn, attr, id);
-               if (!NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
-                       break;
-               }
-       }
-
-       if (NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
-               DEBUG(1,("Failed to increment id %s at %s\n", attr, dn));
-       }
-
-       return status;
-}
-
-
-/*
-  add a string element to a message
-*/
-int samdb_msg_add_string(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
-                        const char *attr_name, const char *str)
-{
-       char *s = talloc_strdup(mem_ctx, str);
-       char *a = talloc_strdup(mem_ctx, attr_name);
-       if (s == NULL || a == NULL) {
+       status = ndr_push_struct_blob(&v, mem_ctx, sid, 
+                                     (ndr_push_flags_fn_t)ndr_push_dom_sid);
+       if (!NT_STATUS_IS_OK(status)) {
                return -1;
        }
-       return ldb_msg_add_string(sam_ctx->ldb, msg, a, s);
+       return ldb_msg_add_value(msg, attr_name, &v);
 }
 
+
 /*
   add a delete element operation to a message
 */
-int samdb_msg_add_delete(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                         const char *attr_name)
 {
        char *a = talloc_strdup(mem_ctx, attr_name);
@@ -742,13 +731,13 @@ int samdb_msg_add_delete(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
        }
        /* we use an empty replace rather than a delete, as it allows for 
           samdb_replace() to be used everywhere */
-       return ldb_msg_add_empty(sam_ctx->ldb, msg, a, LDB_FLAG_MOD_REPLACE);
+       return ldb_msg_add_empty(msg, a, LDB_FLAG_MOD_REPLACE);
 }
 
 /*
   add a add attribute value to a message
 */
-int samdb_msg_add_addval(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                         const char *attr_name, const char *value)
 {
        struct ldb_message_element *el;
@@ -760,7 +749,7 @@ int samdb_msg_add_addval(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
        v = talloc_strdup(mem_ctx, value);
        if (v == NULL)
                return -1;
-       ret = ldb_msg_add_string(sam_ctx->ldb, msg, a, v);
+       ret = ldb_msg_add_string(msg, a, v);
        if (ret != 0)
                return ret;
        el = ldb_msg_find_element(msg, a);
@@ -773,7 +762,7 @@ int samdb_msg_add_addval(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
 /*
   add a delete attribute value to a message
 */
-int samdb_msg_add_delval(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                         const char *attr_name, const char *value)
 {
        struct ldb_message_element *el;
@@ -785,7 +774,7 @@ int samdb_msg_add_delval(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
        v = talloc_strdup(mem_ctx, value);
        if (v == NULL)
                return -1;
-       ret = ldb_msg_add_string(sam_ctx->ldb, msg, a, v);
+       ret = ldb_msg_add_string(msg, a, v);
        if (ret != 0)
                return ret;
        el = ldb_msg_find_element(msg, a);
@@ -798,37 +787,37 @@ int samdb_msg_add_delval(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
 /*
   add a uint_t element to a message
 */
-int samdb_msg_add_uint(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                       const char *attr_name, uint_t v)
 {
        const char *s = talloc_asprintf(mem_ctx, "%u", v);
-       return samdb_msg_add_string(sam_ctx, mem_ctx, msg, attr_name, s);
+       return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
 }
 
 /*
   add a (signed) int64_t element to a message
 */
-int samdb_msg_add_int64(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                        const char *attr_name, int64_t v)
 {
        const char *s = talloc_asprintf(mem_ctx, "%lld", v);
-       return samdb_msg_add_string(sam_ctx, mem_ctx, msg, attr_name, s);
+       return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
 }
 
 /*
   add a uint64_t element to a message
 */
-int samdb_msg_add_uint64(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                        const char *attr_name, uint64_t v)
 {
        const char *s = talloc_asprintf(mem_ctx, "%llu", v);
-       return samdb_msg_add_string(sam_ctx, mem_ctx, msg, attr_name, s);
+       return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
 }
 
 /*
   add a samr_Password element to a message
 */
-int samdb_msg_add_hash(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                       const char *attr_name, struct samr_Password *hash)
 {
        struct ldb_val val;
@@ -837,13 +826,13 @@ int samdb_msg_add_hash(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb
                return -1;
        }
        val.length = 16;
-       return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, &val);
+       return ldb_msg_add_value(msg, attr_name, &val);
 }
 
 /*
   add a samr_Password array to a message
 */
-int samdb_msg_add_hashes(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_hashes(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                         const char *attr_name, struct samr_Password *hashes, uint_t count)
 {
        struct ldb_val val;
@@ -856,44 +845,44 @@ int samdb_msg_add_hashes(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
        for (i=0;i<count;i++) {
                memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
        }
-       return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, &val);
+       return ldb_msg_add_value(msg, attr_name, &val);
 }
 
 /*
   add a acct_flags element to a message
 */
-int samdb_msg_add_acct_flags(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                             const char *attr_name, uint32_t v)
 {
-       return samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr_name, samdb_acb2uf(v));
+       return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
 }
 
 /*
   add a logon_hours element to a message
 */
-int samdb_msg_add_logon_hours(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                              const char *attr_name, struct samr_LogonHours *hours)
 {
        struct ldb_val val;
        val.length = hours->units_per_week / 8;
        val.data = hours->bits;
-       return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, &val);
+       return ldb_msg_add_value(msg, attr_name, &val);
 }
 
 /*
   add a general value element to a message
 */
-int samdb_msg_add_value(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                              const char *attr_name, const struct ldb_val *val)
 {
-       return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, val);
+       return ldb_msg_add_value(msg, attr_name, val);
 }
 
 /*
-  set a string element in a message
+  sets a general value element to a message
 */
-int samdb_msg_set_string(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
-                        const char *attr_name, const char *str)
+int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+                       const char *attr_name, const struct ldb_val *val)
 {
        struct ldb_message_element *el;
 
@@ -901,65 +890,52 @@ int samdb_msg_set_string(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct l
        if (el) {
                el->num_values = 0;
        }
-       return samdb_msg_add_string(sam_ctx, mem_ctx, msg, attr_name, str);
+       return ldb_msg_add_value(msg, attr_name, val);
 }
 
 /*
-  set a ldaptime element in a message
+  set a string element in a message
 */
-int samdb_msg_set_ldaptime(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
-                          const char *attr_name, time_t t)
+int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+                        const char *attr_name, const char *str)
 {
-       char *str = ldap_timestring(mem_ctx, t);
-       if (!str) {
-               return -1;
+       struct ldb_message_element *el;
+
+       el = ldb_msg_find_element(msg, attr_name);
+       if (el) {
+               el->num_values = 0;
        }
-       return samdb_msg_set_string(sam_ctx, mem_ctx, msg, attr_name, str);
+       return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
 }
 
 /*
   add a record
 */
-int samdb_add(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
+int samdb_add(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
 {
-       struct GUID guid;
-       const char *guidstr;
-       time_t now = time(NULL);
-       /* a new GUID */
-       guid = GUID_random();
-       guidstr = GUID_string(mem_ctx, &guid);
-       if (!guidstr) {
-               return -1;
-       }
-
-       samdb_msg_add_string(sam_ctx, mem_ctx, msg, "objectGUID", guidstr);
-       samdb_msg_set_ldaptime(sam_ctx, mem_ctx, msg, "whenCreated", now);
-       samdb_msg_set_ldaptime(sam_ctx, mem_ctx, msg, "whenChanged", now);
-       return ldb_add(sam_ctx->ldb, msg);
+       return ldb_add(sam_ldb, msg);
 }
 
 /*
   delete a record
 */
-int samdb_delete(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, const char *dn)
+int samdb_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const struct ldb_dn *dn)
 {
-       return ldb_delete(sam_ctx->ldb, dn);
+       return ldb_delete(sam_ldb, dn);
 }
 
 /*
   modify a record
 */
-int samdb_modify(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
+int samdb_modify(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
 {
-       time_t now = time(NULL);
-       samdb_msg_set_ldaptime(sam_ctx, mem_ctx, msg, "whenChanged", now);
-       return ldb_modify(sam_ctx->ldb, msg);
+       return ldb_modify(sam_ldb, msg);
 }
 
 /*
   replace elements in a record
 */
-int samdb_replace(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
+int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
 {
        int i;
 
@@ -969,7 +945,7 @@ int samdb_replace(struct ldb_wrap *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_mess
        }
 
        /* modify the samdb record */
-       return samdb_modify(sam_ctx, mem_ctx, msg);
+       return samdb_modify(sam_ldb, mem_ctx, msg);
 }
 
 /*
@@ -983,3 +959,37 @@ struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ct
 
        return sd;
 }
+
+struct ldb_dn *samdb_base_dn(TALLOC_CTX *mem_ctx) 
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       int server_role = lp_server_role();
+       const char **split_realm;
+       struct ldb_dn *dn;
+       
+       if (!tmp_ctx) {
+               return NULL;
+       }
+
+       if ((server_role == ROLE_DOMAIN_PDC)
+           || (server_role == ROLE_DOMAIN_BDC)) {
+               int i;
+               split_realm = str_list_make(tmp_ctx, lp_realm(), ".");
+               if (!split_realm) {
+                       talloc_free(tmp_ctx);
+                       return NULL;
+               }
+               dn = NULL;
+               i = str_list_length(split_realm);
+               i--;
+               for (; i >= 0; i--) {
+                       dn = ldb_dn_build_child(tmp_ctx, "dc", split_realm[i], dn);
+                       if (!dn) {
+                               talloc_free(tmp_ctx);
+                               return NULL;
+                       }
+               }
+               return dn;
+       }
+       return ldb_dn_string_compose(mem_ctx, NULL, "cn=%s", lp_netbios_name());
+}