s3-group-mapping: Remove fstrings from GROUP_MAP.
[samba.git] / source3 / passdb / pdb_ldap.c
index dddde75a4eab30c186b069166a626c24e18ebf82..dd46f8f87f6a8af95f2b7387448d69214d023af6 100644 (file)
 */
 
 #include "includes.h"
+#include "passdb.h"
 #include "../libcli/auth/libcli_auth.h"
+#include "secrets.h"
+#include "idmap_cache.h"
+#include "../libcli/security/security.h"
+#include "../lib/util/util_pw.h"
+#include "lib/winbind_util.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
 #include <lber.h>
 #include <ldap.h>
 
-/*
- * Work around versions of the LDAP client libs that don't have the OIDs
- * defined, or have them defined under the old name.  
- * This functionality is really a factor of the server, not the client 
- *
- */
-
-#if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
-#define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
-#elif !defined(LDAP_EXOP_MODIFY_PASSWD)
-#define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1"
-#endif
-
-#if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
-#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
-#elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
-#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID        ((ber_tag_t) 0x80U)
-#endif
-
-#if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
-#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
-#elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
-#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW       ((ber_tag_t) 0x82U)
-#endif
-
 
 #include "smbldap.h"
+#include "passdb/pdb_ldap.h"
+#include "passdb/pdb_nds.h"
+#include "passdb/pdb_ipa.h"
 
 /**********************************************************************
  Simple helper function to make stuff better readable
  **********************************************************************/
 
-static LDAP *priv2ld(struct ldapsam_privates *priv)
+LDAP *priv2ld(struct ldapsam_privates *priv)
 {
        return priv->smbldap_state->ldap_struct;
 }
@@ -227,7 +211,7 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_
        if (mem_ctx == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       if ((attrs = TALLOC_ARRAY(mem_ctx, const char *, 2)) == NULL) {
+       if ((attrs = talloc_array(mem_ctx, const char *, 2)) == NULL) {
                ntstatus = NT_STATUS_NO_MEMORY;
                goto done;
        }
@@ -336,7 +320,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
                                          const char **attr)
 {
        char *filter = NULL;
-       char *escape_user = escape_ldap_string_alloc(user);
+       char *escape_user = escape_ldap_string(talloc_tos(), user);
        int ret = -1;
 
        if (!escape_user) {
@@ -350,7 +334,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
        filter = talloc_asprintf(talloc_tos(), "(&%s%s)", "(uid=%u)",
                get_objclass_filter(ldap_state->schema_ver));
        if (!filter) {
-               SAFE_FREE(escape_user);
+               TALLOC_FREE(escape_user);
                return LDAP_NO_MEMORY;
        }
        /*
@@ -360,7 +344,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
 
        filter = talloc_all_string_sub(talloc_tos(),
                                filter, "%u", escape_user);
-       SAFE_FREE(escape_user);
+       TALLOC_FREE(escape_user);
        if (!filter) {
                return LDAP_NO_MEMORY;
        }
@@ -376,7 +360,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
 ******************************************************************/
 
 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
-                                        uint32 rid, LDAPMessage ** result,
+                                        uint32_t rid, LDAPMessage ** result,
                                         const char **attr)
 {
        char *filter = NULL;
@@ -399,7 +383,7 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
 ******************************************************************/
 
 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
-                                const DOM_SID *sid, LDAPMessage ** result,
+                                const struct dom_sid *sid, LDAPMessage ** result,
                                 const char **attr)
 {
        char *filter = NULL;
@@ -529,19 +513,19 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        *acct_desc = NULL,
                        *workstations = NULL,
                        *munged_dial = NULL;
-       uint32          user_rid;
+       uint32_t                user_rid;
        uint8           smblmpwd[LM_HASH_LEN],
                        smbntpwd[NT_HASH_LEN];
        bool            use_samba_attrs = True;
-       uint32          acct_ctrl = 0;
-       uint16          logon_divs;
-       uint16          bad_password_count = 0,
+       uint32_t                acct_ctrl = 0;
+       uint16_t                logon_divs;
+       uint16_t                bad_password_count = 0,
                        logon_count = 0;
-       uint32 hours_len;
+       uint32_t hours_len;
        uint8           hours[MAX_HOURS_LEN];
        char *temp = NULL;
-       LOGIN_CACHE     *cache_entry = NULL;
-       uint32          pwHistLen;
+       struct login_cache cache_entry;
+       uint32_t                pwHistLen;
        bool expand_explicit = lp_passdb_expand_explicit();
        bool ret = false;
        TALLOC_CTX *ctx = talloc_init("init_sam_from_ldap");
@@ -560,7 +544,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                goto fn_exit;
        }
 
-       if (!(username = smbldap_talloc_smallest_attribute(priv2ld(ldap_state),
+       if (!(username = smbldap_talloc_first_attribute(priv2ld(ldap_state),
                                        entry,
                                        "uid",
                                        ctx))) {
@@ -604,12 +588,12 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                                get_userattr_key2string(ldap_state->schema_ver,
                                        LDAP_ATTR_USER_RID),
                                ctx))!=NULL) {
-                       user_rid = (uint32)atol(temp);
+                       user_rid = (uint32_t)atol(temp);
                        pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
                }
        }
 
-       if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
+       if (IS_SAM_DEFAULT(sampass, PDB_USERSID)) {
                DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n", 
                        get_userattr_key2string(ldap_state->schema_ver,
                                LDAP_ATTR_USER_SID),
@@ -902,11 +886,11 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
        pwHistLen = 0;
 
-       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
+       pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
        if (pwHistLen > 0){
                uint8 *pwhist = NULL;
                int i;
-               char *history_string = TALLOC_ARRAY(ctx, char,
+               char *history_string = talloc_array(ctx, char,
                                                MAX_PW_HISTORY_LEN*64);
 
                if (!history_string) {
@@ -915,9 +899,9 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
                pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
 
-               if ((pwhist = TALLOC_ARRAY(ctx, uint8,
-                                       pwHistLen * PW_HISTORY_ENTRY_LEN)) ==
-                               NULL){
+               pwhist = talloc_array(ctx, uint8,
+                                     pwHistLen * PW_HISTORY_ENTRY_LEN);
+               if (pwhist == NULL) {
                        DEBUG(0, ("init_sam_from_ldap: talloc failed!\n"));
                        goto fn_exit;
                }
@@ -985,7 +969,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                                LDAP_ATTR_BAD_PASSWORD_COUNT),
                        ctx);
        if (temp) {
-               bad_password_count = (uint32) atol(temp);
+               bad_password_count = (uint32_t) atol(temp);
                pdb_set_bad_password_count(sampass,
                                bad_password_count, PDB_SET);
        }
@@ -1009,7 +993,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                                LDAP_ATTR_LOGON_COUNT),
                        ctx);
        if (temp) {
-               logon_count = (uint32) atol(temp);
+               logon_count = (uint32_t) atol(temp);
                pdb_set_logon_count(sampass, logon_count, PDB_SET);
        }
 
@@ -1024,11 +1008,22 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
        if (temp) {
                pdb_gethexhours(temp, hours);
                memset((char *)temp, '\0', strlen(temp) +1);
-               pdb_set_hours(sampass, hours, PDB_SET);
+               pdb_set_hours(sampass, hours, hours_len, PDB_SET);
                ZERO_STRUCT(hours);
        }
 
        if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+               struct passwd unix_pw;
+               bool have_uid = false;
+               bool have_gid = false;
+               struct dom_sid mapped_gsid;
+               const struct dom_sid *primary_gsid;
+
+               ZERO_STRUCT(unix_pw);
+
+               unix_pw.pw_name = username;
+               unix_pw.pw_passwd = discard_const_p(char, "x");
+
                temp = smbldap_talloc_single_attribute(
                                priv2ld(ldap_state),
                                entry,
@@ -1036,8 +1031,68 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                                ctx);
                if (temp) {
                        /* We've got a uid, feed the cache */
-                       uid_t uid = strtoul(temp, NULL, 10);
-                       store_uid_sid_cache(pdb_get_user_sid(sampass), uid);
+                       unix_pw.pw_uid = strtoul(temp, NULL, 10);
+                       have_uid = true;
+               }
+               temp = smbldap_talloc_single_attribute(
+                               priv2ld(ldap_state),
+                               entry,
+                               "gidNumber",
+                               ctx);
+               if (temp) {
+                       /* We've got a uid, feed the cache */
+                       unix_pw.pw_gid = strtoul(temp, NULL, 10);
+                       have_gid = true;
+               }
+               unix_pw.pw_gecos = smbldap_talloc_single_attribute(
+                               priv2ld(ldap_state),
+                               entry,
+                               "gecos",
+                               ctx);
+               if (unix_pw.pw_gecos) {
+                       unix_pw.pw_gecos = fullname;
+               }
+               unix_pw.pw_dir = smbldap_talloc_single_attribute(
+                               priv2ld(ldap_state),
+                               entry,
+                               "homeDirectory",
+                               ctx);
+               if (unix_pw.pw_dir) {
+                       unix_pw.pw_dir = discard_const_p(char, "");
+               }
+               unix_pw.pw_shell = smbldap_talloc_single_attribute(
+                               priv2ld(ldap_state),
+                               entry,
+                               "loginShell",
+                               ctx);
+               if (unix_pw.pw_shell) {
+                       unix_pw.pw_shell = discard_const_p(char, "");
+               }
+
+               if (have_uid && have_gid) {
+                       sampass->unix_pw = tcopy_passwd(sampass, &unix_pw);
+               } else {
+                       sampass->unix_pw = Get_Pwnam_alloc(sampass, unix_pw.pw_name);
+               }
+
+               if (sampass->unix_pw == NULL) {
+                       DEBUG(0,("init_sam_from_ldap: Failed to find Unix account for %s\n",
+                                pdb_get_username(sampass)));
+                       goto fn_exit;
+               }
+
+               store_uid_sid_cache(pdb_get_user_sid(sampass),
+                                   sampass->unix_pw->pw_uid);
+               idmap_cache_set_sid2uid(pdb_get_user_sid(sampass),
+                                       sampass->unix_pw->pw_uid);
+
+               gid_to_sid(&mapped_gsid, sampass->unix_pw->pw_gid);
+               primary_gsid = pdb_get_group_sid(sampass);
+               if (primary_gsid && dom_sid_equal(primary_gsid, &mapped_gsid)) {
+                       store_gid_sid_cache(primary_gsid,
+                                           sampass->unix_pw->pw_gid);
+                       idmap_cache_set_sid2gid(primary_gsid,
+                                               sampass->unix_pw->pw_gid);
                }
        }
 
@@ -1049,7 +1104,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
        }
 
        /* see if we have newer updates */
-       if (!(cache_entry = login_cache_read(sampass))) {
+       if (!login_cache_read(sampass, &cache_entry)) {
                DEBUG (9, ("No cache entry, bad count = %u, bad time = %u\n",
                           (unsigned int)pdb_get_bad_password_count(sampass),
                           (unsigned int)pdb_get_bad_password_time(sampass)));
@@ -1059,10 +1114,10 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
        DEBUG(7, ("ldap time is %u, cache time is %u, bad time = %u\n",
                  (unsigned int)ldap_entry_time,
-                 (unsigned int)cache_entry->entry_timestamp,
-                 (unsigned int)cache_entry->bad_password_time));
+                 (unsigned int)cache_entry.entry_timestamp,
+                 (unsigned int)cache_entry.bad_password_time));
 
-       if (ldap_entry_time > cache_entry->entry_timestamp) {
+       if (ldap_entry_time > cache_entry.entry_timestamp) {
                /* cache is older than directory , so
                   we need to delete the entry but allow the
                   fields to be written out */
@@ -1071,13 +1126,13 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                /* read cache in */
                pdb_set_acct_ctrl(sampass,
                                  pdb_get_acct_ctrl(sampass) |
-                                 (cache_entry->acct_ctrl & ACB_AUTOLOCK),
+                                 (cache_entry.acct_ctrl & ACB_AUTOLOCK),
                                  PDB_SET);
                pdb_set_bad_password_count(sampass,
-                                          cache_entry->bad_password_count,
+                                          cache_entry.bad_password_count,
                                           PDB_SET);
                pdb_set_bad_password_time(sampass,
-                                         cache_entry->bad_password_time,
+                                         cache_entry.bad_password_time,
                                          PDB_SET);
        }
 
@@ -1086,7 +1141,6 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
   fn_exit:
 
        TALLOC_FREE(ctx);
-       SAFE_FREE(cache_entry);
        return ret;
 }
 
@@ -1102,7 +1156,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                                                    enum pdb_elements))
 {
        char *temp = NULL;
-       uint32 rid;
+       uint32_t rid;
 
        if (mods == NULL || sampass == NULL) {
                DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
@@ -1131,7 +1185,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
        /* only update the RID if we actually need to */
        if (need_update(sampass, PDB_USERSID)) {
                fstring sid_string;
-               const DOM_SID *user_sid = pdb_get_user_sid(sampass);
+               const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
 
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
@@ -1168,7 +1222,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
        if (need_update(sampass, PDB_GROUPSID)) {
                fstring sid_string;
-               const DOM_SID *group_sid = pdb_get_group_sid(sampass);
+               const struct dom_sid *group_sid = pdb_get_group_sid(sampass);
 
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
@@ -1326,8 +1380,8 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
                if (need_update(sampass, PDB_PWHISTORY)) {
                        char *pwstr = NULL;
-                       uint32 pwHistLen = 0;
-                       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
+                       uint32_t pwHistLen = 0;
+                       pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
 
                        pwstr = SMB_MALLOC_ARRAY(char, 1024);
                        if (!pwstr) {
@@ -1339,7 +1393,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                                pwstr[64] = '\0';
                        } else {
                                int i;
-                               uint32 currHistLen = 0;
+                               uint32_t currHistLen = 0;
                                const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen);
                                if (pwhist != NULL) {
                                        /* We can only store (1024-1/64 password history entries. */
@@ -1401,10 +1455,10 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
        if (need_update(sampass, PDB_BAD_PASSWORD_COUNT))  /* &&
            need_update(sampass, PDB_BAD_PASSWORD_TIME)) */ {
-               uint16 badcount = pdb_get_bad_password_count(sampass);
+               uint16_t badcount = pdb_get_bad_password_count(sampass);
                time_t badtime = pdb_get_bad_password_time(sampass);
-               uint32 pol;
-               pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol);
+               uint32_t pol;
+               pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &pol);
 
                DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
                        (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
@@ -1440,7 +1494,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
                        login_cache_delentry(sampass);
                } else {
-                       LOGIN_CACHE cache_entry;
+                       struct login_cache cache_entry;
 
                        cache_entry.entry_timestamp = time(NULL);
                        cache_entry.acct_ctrl = pdb_get_acct_ctrl(sampass);
@@ -1448,7 +1502,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        cache_entry.bad_password_time = badtime;
 
                        DEBUG(7, ("Updating bad password count and time in login cache\n"));
-                       login_cache_write(sampass, cache_entry);
+                       login_cache_write(sampass, &cache_entry);
                }
        }
 
@@ -1481,13 +1535,23 @@ static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
                ;
        }
 
-       (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
+       (*attr_list) = talloc_realloc(mem_ctx, (*attr_list),
                                            const char *,  i+2);
        SMB_ASSERT((*attr_list) != NULL);
        (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
        (*attr_list)[i+1] = NULL;
 }
 
+static void ldapsam_add_unix_attributes(TALLOC_CTX *mem_ctx,
+                                       const char ***attr_list)
+{
+       append_attr(mem_ctx, attr_list, "uidNumber");
+       append_attr(mem_ctx, attr_list, "gidNumber");
+       append_attr(mem_ctx, attr_list, "homeDirectory");
+       append_attr(mem_ctx, attr_list, "loginShell");
+       append_attr(mem_ctx, attr_list, "gecos");
+}
+
 /**********************************************************************
 Get struct samu entry from LDAP by username.
 *********************************************************************/
@@ -1506,7 +1570,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu
        append_attr(user, &attr_list,
                    get_userattr_key2string(ldap_state->schema_ver,
                                            LDAP_ATTR_MOD_TIMESTAMP));
-       append_attr(user, &attr_list, "uidNumber");
+       ldapsam_add_unix_attributes(user, &attr_list);
        rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
                                           attr_list);
        TALLOC_FREE( attr_list );
@@ -1544,11 +1608,11 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu
 }
 
 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, 
-                                  const DOM_SID *sid, LDAPMessage **result) 
+                                  const struct dom_sid *sid, LDAPMessage **result)
 {
        int rc = -1;
        const char ** attr_list;
-       uint32 rid;
+       uint32_t rid;
 
        switch ( ldap_state->schema_ver ) {
                case SCHEMAVER_SAMBASAMACCOUNT: {
@@ -1563,7 +1627,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
                                    get_userattr_key2string(
                                            ldap_state->schema_ver,
                                            LDAP_ATTR_MOD_TIMESTAMP));
-                       append_attr(tmp_ctx, &attr_list, "uidNumber");
+                       ldapsam_add_unix_attributes(tmp_ctx, &attr_list);
                        rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
                                                          result, attr_list);
                        TALLOC_FREE(tmp_ctx);
@@ -1594,7 +1658,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
  Get struct samu entry from LDAP by SID.
 *********************************************************************/
 
-static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
+static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const struct dom_sid *sid)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAPMessage *result = NULL;
@@ -1657,39 +1721,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!mods) {
-               DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
-               /* may be password change below however */
-       } else {
-               switch(ldap_op) {
-                       case LDAP_MOD_ADD:
-                               if (ldap_state->is_nds_ldap) {
-                                       smbldap_set_mod(&mods, LDAP_MOD_ADD, 
-                                                       "objectclass", 
-                                                       "inetOrgPerson");
-                               } else {
-                                       smbldap_set_mod(&mods, LDAP_MOD_ADD, 
-                                                       "objectclass", 
-                                                       LDAP_OBJ_ACCOUNT);
-                               }
-                               rc = smbldap_add(ldap_state->smbldap_state, 
-                                                dn, mods);
-                               break;
-                       case LDAP_MOD_REPLACE: 
-                               rc = smbldap_modify(ldap_state->smbldap_state, 
-                                                   dn ,mods);
-                               break;
-                       default:        
-                               DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n", 
-                                        ldap_op));
-                               return NT_STATUS_INVALID_PARAMETER;
-               }
-
-               if (rc!=LDAP_SUCCESS) {
-                       return NT_STATUS_UNSUCCESSFUL;
-               }  
-       }
-
        if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
                        (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
                        need_update(newpwd, PDB_PLAINTEXT_PW) &&
@@ -1701,6 +1732,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                char *utf8_password;
                char *utf8_dn;
                size_t converted_size;
+               int ret;
 
                if (!ldap_state->is_nds_ldap) {
 
@@ -1732,14 +1764,31 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                }
 
                if ((ber_printf (ber, "{") < 0) ||
-                   (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn) < 0) ||
-                   (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password) < 0) ||
-                   (ber_printf (ber, "n}") < 0)) {
-                       DEBUG(0,("ldapsam_modify_entry: ber_printf returns a value <0\n"));
-                       ber_free(ber,1);
-                       TALLOC_FREE(utf8_dn);
-                       TALLOC_FREE(utf8_password);
-                       return NT_STATUS_UNSUCCESSFUL;
+                   (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
+                                utf8_dn) < 0)) {
+                       DEBUG(0,("ldapsam_modify_entry: ber_printf returns a "
+                                "value <0\n"));
+                       ber_free(ber,1);
+                       TALLOC_FREE(utf8_dn);
+                       TALLOC_FREE(utf8_password);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+
+               if ((utf8_password != NULL) && (*utf8_password != '\0')) {
+                       ret = ber_printf(ber, "ts}",
+                                        LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
+                                        utf8_password);
+               } else {
+                       ret = ber_printf(ber, "}");
+               }
+
+               if (ret < 0) {
+                       DEBUG(0,("ldapsam_modify_entry: ber_printf returns a "
+                                "value <0\n"));
+                       ber_free(ber,1);
+                       TALLOC_FREE(utf8_dn);
+                       TALLOC_FREE(utf8_password);
+                       return NT_STATUS_UNSUCCESSFUL;
                }
 
                if ((rc = ber_flatten (ber, &bv))<0) {
@@ -1797,6 +1846,40 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                }
                ber_bvfree(bv);
        }
+
+       if (!mods) {
+               DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
+               /* may be password change below however */
+       } else {
+               switch(ldap_op) {
+                       case LDAP_MOD_ADD:
+                               if (ldap_state->is_nds_ldap) {
+                                       smbldap_set_mod(&mods, LDAP_MOD_ADD,
+                                                       "objectclass",
+                                                       "inetOrgPerson");
+                               } else {
+                                       smbldap_set_mod(&mods, LDAP_MOD_ADD,
+                                                       "objectclass",
+                                                       LDAP_OBJ_ACCOUNT);
+                               }
+                               rc = smbldap_add(ldap_state->smbldap_state,
+                                                dn, mods);
+                               break;
+                       case LDAP_MOD_REPLACE:
+                               rc = smbldap_modify(ldap_state->smbldap_state,
+                                                   dn ,mods);
+                               break;
+                       default:
+                               DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n",
+                                        ldap_op));
+                               return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (rc!=LDAP_SUCCESS) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
        return NT_STATUS_OK;
 }
 
@@ -1861,17 +1944,6 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
        return result;
 }
 
-/**********************************************************************
- Helper function to determine for update_sam_account whether
- we need LDAP modification.
-*********************************************************************/
-
-static bool element_is_changed(const struct samu *sampass,
-                              enum pdb_elements element)
-{
-       return IS_SAM_CHANGED(sampass, element);
-}
-
 /**********************************************************************
  Update struct samu.
 *********************************************************************/
@@ -1917,7 +1989,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
        DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
 
        if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
-                               element_is_changed)) {
+                               pdb_element_is_changed)) {
                DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
                TALLOC_FREE(dn);
                if (mods != NULL)
@@ -1933,7 +2005,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
                return NT_STATUS_OK;
        }
 
-       ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
+       ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, pdb_element_is_changed);
 
        if (mods != NULL) {
                ldap_mods_free(mods,True);
@@ -1968,6 +2040,18 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
  - The "rename user script" has full responsibility for changing everything
 ***************************************************************************/
 
+static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
+                                    TALLOC_CTX *tmp_ctx,
+                                    uint32_t group_rid,
+                                    uint32_t member_rid);
+
+static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
+                                              TALLOC_CTX *mem_ctx,
+                                              struct samu *user,
+                                              struct dom_sid **pp_sids,
+                                              gid_t **pp_gids,
+                                              uint32_t *p_num_groups);
+
 static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
                                           struct samu *old_acct,
                                           const char *newname)
@@ -2040,18 +2124,6 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
        return NT_STATUS_OK;
 }
 
-/**********************************************************************
- Helper function to determine for update_sam_account whether
- we need LDAP modification.
- *********************************************************************/
-
-static bool element_is_set_or_changed(const struct samu *sampass,
-                                     enum pdb_elements element)
-{
-       return (IS_SAM_SET(sampass, element) ||
-               IS_SAM_CHANGED(sampass, element));
-}
-
 /**********************************************************************
  Add struct samu to LDAP.
 *********************************************************************/
@@ -2065,11 +2137,11 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
        LDAPMessage     *entry  = NULL;
        LDAPMod         **mods = NULL;
        int             ldap_op = LDAP_MOD_REPLACE;
-       uint32          num_result;
+       uint32_t                num_result;
        const char      **attr_list;
        char *escape_user = NULL;
        const char      *username = pdb_get_username(newpwd);
-       const DOM_SID   *sid = pdb_get_user_sid(newpwd);
+       const struct dom_sid    *sid = pdb_get_user_sid(newpwd);
        char *filter = NULL;
        char *dn = NULL;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
@@ -2102,7 +2174,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
        ldap_msgfree(result);
        result = NULL;
 
-       if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
+       if (pdb_element_is_set_or_changed(newpwd, PDB_USERSID)) {
                rc = ldapsam_get_ldap_user_by_sid(ldap_state,
                                                  sid, &result);
                if (rc == LDAP_SUCCESS) {
@@ -2120,18 +2192,18 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
        /* does the entry already exist but without a samba attributes?
           we need to return the samba attributes here */
 
-       escape_user = escape_ldap_string_alloc( username );
+       escape_user = escape_ldap_string(talloc_tos(), username);
        filter = talloc_strdup(attr_list, "(uid=%u)");
        if (!filter) {
                status = NT_STATUS_NO_MEMORY;
                goto fn_exit;
        }
        filter = talloc_all_string_sub(attr_list, filter, "%u", escape_user);
+       TALLOC_FREE(escape_user);
        if (!filter) {
                status = NT_STATUS_NO_MEMORY;
                goto fn_exit;
        }
-       SAFE_FREE(escape_user);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state,
                                   filter, attr_list, &result);
@@ -2238,7 +2310,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
        }
 
        if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
-                               element_is_set_or_changed)) {
+                               pdb_element_is_set_or_changed)) {
                DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
                if (mods != NULL) {
                        ldap_mods_free(mods, true);
@@ -2262,7 +2334,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
                        break;
        }
 
-       ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
+       ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, pdb_element_is_set_or_changed);
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n",
                         pdb_get_username(newpwd),dn));
@@ -2278,7 +2350,6 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
   fn_exit:
 
        TALLOC_FREE(ctx);
-       SAFE_FREE(escape_user);
        if (result) {
                ldap_msgfree(result);
        }
@@ -2298,7 +2369,7 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
 
        attr_list = get_attr_list(NULL, groupmap_attr_list);
        rc = smbldap_search(ldap_state->smbldap_state,
-                           lp_ldap_group_suffix (), scope,
+                           lp_ldap_suffix (), scope,
                            filter, attr_list, 0, result);
        TALLOC_FREE(attr_list);
 
@@ -2400,7 +2471,11 @@ for gidNumber(%lu)\n",(unsigned long)map->gid));
                        return false;
                }
        }
-       fstrcpy(map->nt_name, temp);
+       map->nt_name = talloc_strdup(map, temp);
+       if (!map->nt_name) {
+               TALLOC_FREE(ctx);
+               return false;
+       }
 
        TALLOC_FREE(temp);
        temp = smbldap_talloc_single_attribute(
@@ -2416,10 +2491,15 @@ for gidNumber(%lu)\n",(unsigned long)map->gid));
                        return false;
                }
        }
-       fstrcpy(map->comment, temp);
+       map->comment = talloc_strdup(map, temp);
+       if (!map->comment) {
+               TALLOC_FREE(ctx);
+               return false;
+       }
 
        if (lp_parm_bool(-1, "ldapsam", "trusted", false)) {
                store_gid_sid_cache(&map->sid, map->gid);
+               idmap_cache_set_sid2gid(&map->sid, map->gid);
        }
 
        TALLOC_FREE(ctx);
@@ -2482,7 +2562,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
  *********************************************************************/
 
 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
-                                DOM_SID sid)
+                                struct dom_sid sid)
 {
        char *filter = NULL;
        NTSTATUS status;
@@ -2528,7 +2608,7 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
                                 const char *name)
 {
        char *filter = NULL;
-       char *escape_name = escape_ldap_string_alloc(name);
+       char *escape_name = escape_ldap_string(talloc_tos(), name);
        NTSTATUS status;
 
        if (!escape_name) {
@@ -2540,11 +2620,11 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
                get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
                get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN),
                escape_name) < 0) {
-               SAFE_FREE(escape_name);
+               TALLOC_FREE(escape_name);
                return NT_STATUS_NO_MEMORY;
        }
 
-       SAFE_FREE(escape_name);
+       TALLOC_FREE(escape_name);
        status = ldapsam_getgroup(methods, filter, map);
        SAFE_FREE(filter);
        return status;
@@ -2552,11 +2632,11 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
 
 static bool ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
                                           LDAPMessage *entry,
-                                          const DOM_SID *domain_sid,
-                                          uint32 *rid)
+                                          const struct dom_sid *domain_sid,
+                                          uint32_t *rid)
 {
        fstring str;
-       DOM_SID sid;
+       struct dom_sid sid;
 
        if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
                                          str, sizeof(str)-1)) {
@@ -2569,7 +2649,7 @@ static bool ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
                return False;
        }
 
-       if (sid_compare_domain(&sid, domain_sid) != 0) {
+       if (dom_sid_compare_domain(&sid, domain_sid) != 0) {
                DEBUG(10, ("SID %s is not in expected domain %s\n",
                           str, sid_string_dbg(domain_sid)));
                return False;
@@ -2585,8 +2665,8 @@ static bool ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
 
 static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                                           TALLOC_CTX *mem_ctx,
-                                          const DOM_SID *group,
-                                          uint32 **pp_member_rids,
+                                          const struct dom_sid *group,
+                                          uint32_t **pp_member_rids,
                                           size_t *p_num_members)
 {
        struct ldapsam_privates *ldap_state =
@@ -2618,7 +2698,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                goto done;
        }
 
-       rc = smbldap_search(conn, lp_ldap_group_suffix(),
+       rc = smbldap_search(conn, lp_ldap_suffix(),
                            LDAP_SCOPE_SUBTREE, filter, id_attrs, 0,
                            &result);
 
@@ -2654,7 +2734,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 
        values = ldap_get_values(conn->ldap_struct, entry, "memberUid");
 
-       if (values) {
+       if ((values != NULL) && (values[0] != NULL)) {
 
                filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBASAMACCOUNT);
                if (filter == NULL) {
@@ -2665,20 +2745,19 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                for (memberuid = values; *memberuid != NULL; memberuid += 1) {
                        char *escape_memberuid;
 
-                       escape_memberuid = escape_ldap_string_alloc(*memberuid);
+                       escape_memberuid = escape_ldap_string(talloc_tos(),
+                                                             *memberuid);
                        if (escape_memberuid == NULL) {
                                ret = NT_STATUS_NO_MEMORY;
                                goto done;
                        }
 
                        filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid);
+                       TALLOC_FREE(escape_memberuid);
                        if (filter == NULL) {
-                               SAFE_FREE(escape_memberuid);
                                ret = NT_STATUS_NO_MEMORY;
                                goto done;
                        }
-
-                       SAFE_FREE(escape_memberuid);
                }
 
                filter = talloc_asprintf_append_buffer(filter, "))");
@@ -2704,8 +2783,8 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                     entry = ldap_next_entry(conn->ldap_struct, entry))
                {
                        char *sidstr;
-                       DOM_SID sid;
-                       uint32 rid;
+                       struct dom_sid sid;
+                       uint32_t rid;
 
                        sidstr = smbldap_talloc_single_attribute(conn->ldap_struct,
                                                                 entry, "sambaSID",
@@ -2756,7 +2835,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
             entry != NULL;
             entry = ldap_next_entry(conn->ldap_struct, entry))
        {
-               uint32 rid;
+               uint32_t rid;
 
                if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
                                                    entry,
@@ -2787,9 +2866,9 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                                               TALLOC_CTX *mem_ctx,
                                               struct samu *user,
-                                              DOM_SID **pp_sids,
+                                              struct dom_sid **pp_sids,
                                               gid_t **pp_gids,
-                                              size_t *p_num_groups)
+                                              uint32_t *p_num_groups)
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
@@ -2801,7 +2880,8 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
        LDAPMessage *result = NULL;
        LDAPMessage *entry;
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       size_t num_sids, num_gids;
+       uint32_t num_sids;
+       uint32_t num_gids;
        char *gidstr;
        gid_t primary_gid = -1;
 
@@ -2812,50 +2892,54 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       escape_name = escape_ldap_string_alloc(pdb_get_username(user));
+       escape_name = escape_ldap_string(talloc_tos(), pdb_get_username(user));
        if (escape_name == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       /* retrieve the users primary gid */
-       filter = talloc_asprintf(mem_ctx,
-                                "(&(objectClass=%s)(uid=%s))",
-                                LDAP_OBJ_SAMBASAMACCOUNT,
-                                escape_name);
-       if (filter == NULL) {
-               ret = NT_STATUS_NO_MEMORY;
-               goto done;
-       }
+       if (user->unix_pw) {
+               primary_gid = user->unix_pw->pw_gid;
+       } else {
+               /* retrieve the users primary gid */
+               filter = talloc_asprintf(mem_ctx,
+                                        "(&(objectClass=%s)(uid=%s))",
+                                        LDAP_OBJ_SAMBASAMACCOUNT,
+                                        escape_name);
+               if (filter == NULL) {
+                       ret = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
 
-       rc = smbldap_search(conn, lp_ldap_suffix(),
-                           LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
+               rc = smbldap_search(conn, lp_ldap_suffix(),
+                                   LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
 
-       if (rc != LDAP_SUCCESS)
-               goto done;
+               if (rc != LDAP_SUCCESS)
+                       goto done;
 
-       talloc_autofree_ldapmsg(mem_ctx, result);
+               talloc_autofree_ldapmsg(mem_ctx, result);
 
-       count = ldap_count_entries(priv2ld(ldap_state), result);
+               count = ldap_count_entries(priv2ld(ldap_state), result);
 
-       switch (count) {
-       case 0: 
-               DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
-               ret = NT_STATUS_NO_SUCH_USER;
-               goto done;
-       case 1:
-               entry = ldap_first_entry(priv2ld(ldap_state), result);
+               switch (count) {
+               case 0:
+                       DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
+                       ret = NT_STATUS_NO_SUCH_USER;
+                       goto done;
+               case 1:
+                       entry = ldap_first_entry(priv2ld(ldap_state), result);
 
-               gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
-               if (!gidstr) {
-                       DEBUG (1, ("Unable to find the member's gid!\n"));
+                       gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
+                       if (!gidstr) {
+                               DEBUG (1, ("Unable to find the member's gid!\n"));
+                               ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+                               goto done;
+                       }
+                       primary_gid = strtoul(gidstr, NULL, 10);
+                       break;
+               default:
+                       DEBUG(1, ("found more than one account with the same user name ?!\n"));
                        ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
                        goto done;
                }
-               primary_gid = strtoul(gidstr, NULL, 10);
-               break;
-       default:
-               DEBUG(1, ("found more than one account with the same user name ?!\n"));
-               ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
-               goto done;
        }
 
        filter = talloc_asprintf(mem_ctx,
@@ -2866,7 +2950,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                goto done;
        }
 
-       rc = smbldap_search(conn, lp_ldap_group_suffix(),
+       rc = smbldap_search(conn, lp_ldap_suffix(),
                            LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
 
        if (rc != LDAP_SUCCESS)
@@ -2900,7 +2984,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
             entry = ldap_next_entry(conn->ldap_struct, entry))
        {
                fstring str;
-               DOM_SID sid;
+               struct dom_sid sid;
                gid_t gid;
                char *end;
 
@@ -2938,7 +3022,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                }
        }
 
-       if (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
+       if (dom_sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
                DEBUG(3, ("primary group of [%s] not found\n",
                          pdb_get_username(user)));
                goto done;
@@ -2950,7 +3034,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
  done:
 
-       SAFE_FREE(escape_name);
+       TALLOC_FREE(escape_name);
        return ret;
 }
 
@@ -3025,7 +3109,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
        TALLOC_CTX *mem_ctx;
        NTSTATUS result;
 
-       DOM_SID sid;
+       struct dom_sid sid;
 
        int rc;
 
@@ -3230,7 +3314,7 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
  *********************************************************************/
 
 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
-                                                  DOM_SID sid)
+                                                  struct dom_sid sid)
 {
        struct ldapsam_privates *priv =
                (struct ldapsam_privates *)methods->private_data;
@@ -3324,7 +3408,7 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
                return NT_STATUS_NO_MEMORY;
        }
        attr_list = get_attr_list( NULL, groupmap_attr_list );
-       rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
+       rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
                            LDAP_SCOPE_SUBTREE, filter,
                            attr_list, 0, &ldap_state->result);
        TALLOC_FREE(attr_list);
@@ -3333,7 +3417,7 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
                DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
                          ldap_err2string(rc)));
                DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
-                         lp_ldap_group_suffix(), filter));
+                         lp_ldap_suffix(), filter));
                ldap_msgfree(ldap_state->result);
                ldap_state->result = NULL;
                TALLOC_FREE(filter);
@@ -3393,16 +3477,16 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
  *********************************************************************/
 
 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
-                                          const DOM_SID *domsid, enum lsa_SidType sid_name_use,
-                                          GROUP_MAP **pp_rmap,
+                                          const struct dom_sid *domsid, enum lsa_SidType sid_name_use,
+                                          GROUP_MAP ***pp_rmap,
                                           size_t *p_num_entries,
                                           bool unix_only)
 {
-       GROUP_MAP map;
+       GROUP_MAP *map = NULL;
        size_t entries = 0;
 
        *p_num_entries = 0;
-       *pp_rmap = NULL;
+       **pp_rmap = NULL;
 
        if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
                DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
@@ -3410,31 +3494,44 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
+       while (true) {
+
+               map = talloc_zero(NULL, GROUP_MAP);
+               if (!map) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if (!NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, map))) {
+                       TALLOC_FREE(map);
+                       break;
+               }
+
                if (sid_name_use != SID_NAME_UNKNOWN &&
-                   sid_name_use != map.sid_name_use) {
+                   sid_name_use != map->sid_name_use) {
                        DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
-                                 "not of the requested type\n", map.nt_name));
+                                 "not of the requested type\n",
+                                 map->nt_name));
                        continue;
                }
-               if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
+               if (unix_only == ENUM_ONLY_MAPPED && map->gid == -1) {
                        DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
-                                 "non mapped\n", map.nt_name));
+                                 "non mapped\n", map->nt_name));
                        continue;
                }
 
-               (*pp_rmap)=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
+               *pp_rmap = talloc_realloc(NULL, *pp_rmap,
+                                               GROUP_MAP *, entries + 1);
                if (!(*pp_rmap)) {
                        DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
                                 "enlarge group map!\n"));
                        return NT_STATUS_UNSUCCESSFUL;
                }
 
-               (*pp_rmap)[entries] = map;
+               (*pp_rmap)[entries] = talloc_move((*pp_rmap), &map);
 
                entries += 1;
-
        }
+
        ldapsam_endsamgrent(methods);
 
        *p_num_entries = entries;
@@ -3443,8 +3540,8 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
 }
 
 static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
-                                       const DOM_SID *alias,
-                                       const DOM_SID *member,
+                                       const struct dom_sid *alias,
+                                       const struct dom_sid *member,
                                        int modop)
 {
        struct ldapsam_privates *ldap_state =
@@ -3548,24 +3645,24 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
 }
 
 static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
-                                    const DOM_SID *alias,
-                                    const DOM_SID *member)
+                                    const struct dom_sid *alias,
+                                    const struct dom_sid *member)
 {
        return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
 }
 
 static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
-                                    const DOM_SID *alias,
-                                    const DOM_SID *member)
+                                    const struct dom_sid *alias,
+                                    const struct dom_sid *member)
 {
        return ldapsam_modify_aliasmem(methods, alias, member,
                                       LDAP_MOD_DELETE);
 }
 
 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
-                                     const DOM_SID *alias,
+                                     const struct dom_sid *alias,
                                      TALLOC_CTX *mem_ctx,
-                                     DOM_SID **pp_members,
+                                     struct dom_sid **pp_members,
                                      size_t *p_num_members)
 {
        struct ldapsam_privates *ldap_state =
@@ -3576,7 +3673,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
        char **values = NULL;
        int i;
        char *filter = NULL;
-       size_t num_members = 0;
+       uint32_t num_members = 0;
        enum lsa_SidType type = SID_NAME_USE_NONE;
        fstring tmp;
 
@@ -3651,7 +3748,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
        count = ldap_count_values(values);
 
        for (i=0; i<count; i++) {
-               DOM_SID member;
+               struct dom_sid member;
                NTSTATUS status;
 
                if (!string_to_sid(&member, values[i]))
@@ -3675,10 +3772,10 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
 
 static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
                                          TALLOC_CTX *mem_ctx,
-                                         const DOM_SID *domain_sid,
-                                         const DOM_SID *members,
+                                         const struct dom_sid *domain_sid,
+                                         const struct dom_sid *members,
                                          size_t num_members,
-                                         uint32 **pp_alias_rids,
+                                         uint32_t **pp_alias_rids,
                                          size_t *p_num_alias_rids)
 {
        struct ldapsam_privates *ldap_state =
@@ -3693,8 +3790,14 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
        int rc;
        char *filter;
        enum lsa_SidType type = SID_NAME_USE_NONE;
+       bool is_builtin = false;
+       bool sid_added = false;
+
+       *pp_alias_rids = NULL;
+       *p_num_alias_rids = 0;
 
        if (sid_check_is_builtin(domain_sid)) {
+               is_builtin = true;
                type = SID_NAME_ALIAS;
        }
 
@@ -3708,8 +3811,12 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
+       if (num_members == 0) {
+               return NT_STATUS_OK;
+       }
+
        filter = talloc_asprintf(mem_ctx,
-                                "(&(|(objectclass=%s)(sambaGroupType=%d))(|",
+                                "(&(objectclass=%s)(sambaGroupType=%d)(|",
                                 LDAP_OBJ_GROUPMAP, type);
 
        for (i=0; i<num_members; i++)
@@ -3724,11 +3831,20 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
                return NT_STATUS_NO_MEMORY;
        }
 
-       rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
-                           LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
-
-       if (rc != LDAP_SUCCESS)
-               return NT_STATUS_UNSUCCESSFUL;
+       if (is_builtin &&
+           ldap_state->search_cache.filter &&
+           strcmp(ldap_state->search_cache.filter, filter) == 0) {
+               filter = talloc_move(filter, &ldap_state->search_cache.filter);
+               result = ldap_state->search_cache.result;
+               ldap_state->search_cache.result = NULL;
+       } else {
+               rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
+                                   LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
+               if (rc != LDAP_SUCCESS) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+               talloc_autofree_ldapmsg(filter, result);
+       }
 
        ldap_struct = ldap_state->smbldap_state->ldap_struct;
 
@@ -3737,8 +3853,8 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
             entry = ldap_next_entry(ldap_struct, entry))
        {
                fstring sid_str;
-               DOM_SID sid;
-               uint32 rid;
+               struct dom_sid sid;
+               uint32_t rid;
 
                if (!smbldap_get_single_attribute(ldap_struct, entry,
                                                  LDAP_ATTRIBUTE_SID,
@@ -3752,20 +3868,30 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
                if (!sid_peek_check_rid(domain_sid, &sid, &rid))
                        continue;
 
+               sid_added = true;
+
                if (!add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
                                        p_num_alias_rids)) {
-                       ldap_msgfree(result);
                        return NT_STATUS_NO_MEMORY;
                }
        }
 
-       ldap_msgfree(result);
+       if (!is_builtin && !sid_added) {
+               TALLOC_FREE(ldap_state->search_cache.filter);
+               /*
+                * Note: result is a talloc child of filter because of the
+                * talloc_autofree_ldapmsg() usage
+                */
+               ldap_state->search_cache.filter = talloc_move(ldap_state, &filter);
+               ldap_state->search_cache.result = result;
+       }
+
        return NT_STATUS_OK;
 }
 
 static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
-                                                  int policy_index,
-                                                  uint32 value)
+                                                  enum pdb_policy_type type,
+                                                  uint32_t value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
        int rc;
@@ -3782,7 +3908,7 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       policy_attr = get_account_policy_attr(policy_index);
+       policy_attr = get_account_policy_attr(type);
        if (policy_attr == NULL) {
                DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
                         "policy\n"));
@@ -3802,7 +3928,7 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
                return ntstatus;
        }
 
-       if (!cache_account_policy_set(policy_index, value)) {
+       if (!cache_account_policy_set(type, value)) {
                DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
                         "update local tdb cache\n"));
                return ntstatus;
@@ -3812,15 +3938,16 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
 }
 
 static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
-                                          int policy_index, uint32 value)
+                                          enum pdb_policy_type type,
+                                          uint32_t value)
 {
-       return ldapsam_set_account_policy_in_ldap(methods, policy_index,
+       return ldapsam_set_account_policy_in_ldap(methods, type,
                                                  value);
 }
 
 static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
-                                                    int policy_index,
-                                                    uint32 *value)
+                                                    enum pdb_policy_type type,
+                                                    uint32_t *value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
        LDAPMessage *result = NULL;
@@ -3828,6 +3955,7 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
        int count;
        int rc;
        char **vals = NULL;
+       char *filter;
        const char *policy_attr = NULL;
 
        struct ldapsam_privates *ldap_state =
@@ -3841,20 +3969,24 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       policy_attr = get_account_policy_attr(policy_index);
+       policy_attr = get_account_policy_attr(type);
        if (!policy_attr) {
                DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
-                        "policy index: %d\n", policy_index));
+                        "policy index: %d\n", type));
                return ntstatus;
        }
 
        attrs[0] = policy_attr;
        attrs[1] = NULL;
 
+       filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)", LDAP_OBJ_DOMINFO);
+       if (filter == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
        rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
-                           LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
+                           LDAP_SCOPE_BASE, filter, attrs, 0,
                            &result);
-
+       TALLOC_FREE(filter);
        if (rc != LDAP_SUCCESS) {
                return ntstatus;
        }
@@ -3874,7 +4006,7 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
                goto out;
        }
 
-       *value = (uint32)atol(vals[0]);
+       *value = (uint32_t)atol(vals[0]);
 
        ntstatus = NT_STATUS_OK;
 
@@ -3898,17 +4030,18 @@ out:
    Guenther
 */
 static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
-                                          int policy_index, uint32 *value)
+                                          enum pdb_policy_type type,
+                                          uint32_t *value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
 
-       if (cache_account_policy_get(policy_index, value)) {
+       if (cache_account_policy_get(type, value)) {
                DEBUG(11,("ldapsam_get_account_policy: got valid value from "
                          "cache\n"));
                return NT_STATUS_OK;
        }
 
-       ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index,
+       ntstatus = ldapsam_get_account_policy_from_ldap(methods, type,
                                                        value);
        if (NT_STATUS_IS_OK(ntstatus)) {
                goto update_cache;
@@ -3919,27 +4052,27 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
 
 #if 0
        /* should we automagically migrate old tdb value here ? */
-       if (account_policy_get(policy_index, value))
+       if (account_policy_get(type, value))
                goto update_ldap;
 
        DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
-                 "default\n", policy_index));
+                 "default\n", type));
 #endif
 
-       if (!account_policy_get_default(policy_index, value)) {
+       if (!account_policy_get_default(type, value)) {
                return ntstatus;
        }
 
 /* update_ldap: */
 
-       ntstatus = ldapsam_set_account_policy(methods, policy_index, *value);
+       ntstatus = ldapsam_set_account_policy(methods, type, *value);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                return ntstatus;
        }
 
  update_cache:
 
-       if (!cache_account_policy_set(policy_index, *value)) {
+       if (!cache_account_policy_set(type, *value)) {
                DEBUG(0,("ldapsam_get_account_policy: failed to update local "
                         "tdb as a cache\n"));
                return NT_STATUS_UNSUCCESSFUL;
@@ -3949,9 +4082,9 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
 }
 
 static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
-                                   const DOM_SID *domain_sid,
+                                   const struct dom_sid *domain_sid,
                                    int num_rids,
-                                   uint32 *rids,
+                                   uint32_t *rids,
                                    const char **names,
                                    enum lsa_SidType *attrs)
 {
@@ -3992,7 +4125,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
        }
 
        for (i=0; i<num_rids; i++) {
-               DOM_SID sid;
+               struct dom_sid sid;
                sid_compose(&sid, domain_sid, rids[i]);
                allsids = talloc_asprintf_append_buffer(
                        allsids, "(sambaSid=%s)",
@@ -4032,7 +4165,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
        for (entry = ldap_first_entry(ld, msg);
             entry != NULL;
             entry = ldap_next_entry(ld, entry)) {
-               uint32 rid;
+               uint32_t rid;
                int rid_index;
                const char *name;
 
@@ -4085,7 +4218,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                }
 
                rc = smbldap_search(ldap_state->smbldap_state,
-                                   lp_ldap_group_suffix(),
+                                   lp_ldap_suffix(),
                                    LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
                                    &msg);
                talloc_autofree_ldapmsg(mem_ctx, msg);
@@ -4106,7 +4239,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
             entry != NULL;
             entry = ldap_next_entry(ld, entry))
        {
-               uint32 rid;
+               uint32_t rid;
                int rid_index;
                const char *attr;
                enum lsa_SidType type;
@@ -4185,19 +4318,19 @@ static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
                goto done;
        }
 
-       escaped = escape_ldap_string_alloc(username);
+       escaped = escape_ldap_string(talloc_tos(), username);
        if (escaped == NULL) goto done;
 
        result = talloc_string_sub(mem_ctx, filter, "%u", username);
 
  done:
        SAFE_FREE(filter);
-       SAFE_FREE(escaped);
+       TALLOC_FREE(escaped);
 
        return result;
 }
 
-const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
+static const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
 {
        int i, num = 0;
        va_list ap;
@@ -4208,7 +4341,7 @@ const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
                num += 1;
        va_end(ap);
 
-       if ((result = TALLOC_ARRAY(mem_ctx, const char *, num+1)) == NULL) {
+       if ((result = talloc_array(mem_ctx, const char *, num+1)) == NULL) {
                return NULL;
        }
 
@@ -4230,8 +4363,8 @@ const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
 struct ldap_search_state {
        struct smbldap_state *connection;
 
-       uint32 acct_flags;
-       uint16 group_type;
+       uint32_t acct_flags;
+       uint16_t group_type;
 
        const char *base;
        int scope;
@@ -4292,11 +4425,6 @@ static bool ldapsam_search_firstpage(struct pdb_search *search)
         }
         state->current_entry = ldap_first_entry(ld, state->entries);
 
-       if (state->current_entry == NULL) {
-               ldap_msgfree(state->entries);
-               state->entries = NULL;
-       }
-
        return True;
 }
 
@@ -4325,6 +4453,7 @@ static bool ldapsam_search_nextpage(struct pdb_search *search)
        if (state->current_entry == NULL) {
                ldap_msgfree(state->entries);
                state->entries = NULL;
+               return false;
        }
 
        return True;
@@ -4345,6 +4474,10 @@ static bool ldapsam_search_next_entry(struct pdb_search *search,
            !ldapsam_search_nextpage(search))
                    return False;
 
+       if (state->current_entry == NULL) {
+               return false;
+       }
+
        result = state->ldap2displayentry(state, search,
                                          state->connection->ldap_struct,
                                          state->current_entry, entry);
@@ -4406,8 +4539,8 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
 {
        char **vals;
        size_t converted_size;
-       DOM_SID sid;
-       uint32 acct_flags;
+       struct dom_sid sid;
+       uint32_t acct_flags;
 
        vals = ldap_get_values(ld, entry, "sambaAcctFlags");
        if ((vals == NULL) || (vals[0] == NULL)) {
@@ -4432,7 +4565,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
                return False;
        }
        if (!pull_utf8_talloc(mem_ctx,
-                             CONST_DISCARD(char **, &result->account_name),
+                             discard_const_p(char *, &result->account_name),
                              vals[0], &converted_size))
        {
                DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
@@ -4445,7 +4578,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
        if ((vals == NULL) || (vals[0] == NULL))
                DEBUG(8, ("\"displayName\" not found\n"));
        else if (!pull_utf8_talloc(mem_ctx,
-                                  CONST_DISCARD(char **, &result->fullname),
+                                  discard_const_p(char *, &result->fullname),
                                   vals[0], &converted_size))
        {
                DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
@@ -4458,7 +4591,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
        if ((vals == NULL) || (vals[0] == NULL))
                DEBUG(8, ("\"description\" not found\n"));
        else if (!pull_utf8_talloc(mem_ctx,
-                                  CONST_DISCARD(char **, &result->description),
+                                  discard_const_p(char *, &result->description),
                                   vals[0], &converted_size))
        {
                DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
@@ -4499,7 +4632,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
 
 static bool ldapsam_search_users(struct pdb_methods *methods,
                                 struct pdb_search *search,
-                                uint32 acct_flags)
+                                uint32_t acct_flags)
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
@@ -4552,8 +4685,8 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
 {
        char **vals;
        size_t converted_size;
-       DOM_SID sid;
-       uint16 group_type;
+       struct dom_sid sid;
+       uint16_t group_type;
 
        result->account_name = "";
        result->fullname = "";
@@ -4592,7 +4725,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                        return False;
                }
                if (!pull_utf8_talloc(mem_ctx,
-                                     CONST_DISCARD(char **,
+                                     discard_const_p(char *,
                                                    &result->account_name),
                                      vals[0], &converted_size))
                {
@@ -4601,7 +4734,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                }
        }
        else if (!pull_utf8_talloc(mem_ctx,
-                                  CONST_DISCARD(char **,
+                                  discard_const_p(char *,
                                                 &result->account_name),
                                   vals[0], &converted_size))
        {
@@ -4615,7 +4748,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
        if ((vals == NULL) || (vals[0] == NULL))
                DEBUG(8, ("\"description\" not found\n"));
        else if (!pull_utf8_talloc(mem_ctx,
-                                  CONST_DISCARD(char **, &result->description),
+                                  discard_const_p(char *, &result->description),
                                   vals[0], &converted_size))
        {
                DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
@@ -4660,7 +4793,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                        break;
 
                default:
-                       DEBUG(0,("unkown group type: %d\n", group_type));
+                       DEBUG(0,("unknown group type: %d\n", group_type));
                        return False;
        }
 
@@ -4671,7 +4804,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
 
 static bool ldapsam_search_grouptype(struct pdb_methods *methods,
                                     struct pdb_search *search,
-                                     const DOM_SID *sid,
+                                     const struct dom_sid *sid,
                                     enum lsa_SidType type)
 {
        struct ldapsam_privates *ldap_state =
@@ -4687,7 +4820,7 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods,
 
        state->connection = ldap_state->smbldap_state;
 
-       state->base = talloc_strdup(search, lp_ldap_group_suffix());
+       state->base = talloc_strdup(search, lp_ldap_suffix());
        state->connection = ldap_state->smbldap_state;
        state->scope = LDAP_SCOPE_SUBTREE;
        state->filter = talloc_asprintf(search, "(&(objectclass=%s)"
@@ -4723,18 +4856,18 @@ static bool ldapsam_search_groups(struct pdb_methods *methods,
 
 static bool ldapsam_search_aliases(struct pdb_methods *methods,
                                   struct pdb_search *search,
-                                  const DOM_SID *sid)
+                                  const struct dom_sid *sid)
 {
        return ldapsam_search_grouptype(methods, search, sid, SID_NAME_ALIAS);
 }
 
-static bool ldapsam_rid_algorithm(struct pdb_methods *methods)
+static uint32_t ldapsam_capabilities(struct pdb_methods *methods)
 {
-       return False;
+       return PDB_CAP_STORE_RIDS;
 }
 
 static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
-                                   uint32 *rid)
+                                   uint32_t *rid)
 {
        struct smbldap_state *smbldap_state = priv->smbldap_state;
 
@@ -4744,7 +4877,7 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
        NTSTATUS status;
        char *value;
        int rc;
-       uint32 nextRid = 0;
+       uint32_t nextRid = 0;
        const char *dn;
 
        TALLOC_CTX *mem_ctx;
@@ -4781,21 +4914,21 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
        value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
                                                "sambaNextRid", mem_ctx);
        if (value != NULL) {
-               uint32 tmp = (uint32)strtoul(value, NULL, 10);
+               uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
                nextRid = MAX(nextRid, tmp);
        }
 
        value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
                                                "sambaNextUserRid", mem_ctx);
        if (value != NULL) {
-               uint32 tmp = (uint32)strtoul(value, NULL, 10);
+               uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
                nextRid = MAX(nextRid, tmp);
        }
 
        value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
                                                "sambaNextGroupRid", mem_ctx);
        if (value != NULL) {
-               uint32 tmp = (uint32)strtoul(value, NULL, 10);
+               uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
                nextRid = MAX(nextRid, tmp);
        }
 
@@ -4830,7 +4963,7 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
        return status;
 }
 
-static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *rid)
+static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32_t *rid)
 {
        int i;
 
@@ -4852,14 +4985,14 @@ static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *ri
        return NT_STATUS_ACCESS_DENIED;
 }
 
-static bool ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
+static bool ldapsam_new_rid(struct pdb_methods *methods, uint32_t *rid)
 {
        NTSTATUS result = ldapsam_new_rid_internal(methods, rid);
        return NT_STATUS_IS_OK(result) ? True : False;
 }
 
 static bool ldapsam_sid_to_id(struct pdb_methods *methods,
-                             const DOM_SID *sid,
+                             const struct dom_sid *sid,
                              union unid_t *id, enum lsa_SidType *type)
 {
        struct ldapsam_privates *priv =
@@ -4924,6 +5057,8 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
 
                id->gid = strtoul(gid_str, NULL, 10);
                *type = (enum lsa_SidType)strtoul(value, NULL, 10);
+               store_gid_sid_cache(sid, id->gid);
+               idmap_cache_set_sid2gid(sid, id->gid);
                ret = True;
                goto done;
        }
@@ -4940,6 +5075,8 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
 
        id->uid = strtoul(value, NULL, 10);
        *type = SID_NAME_USER;
+       store_uid_sid_cache(sid, id->uid);
+       idmap_cache_set_sid2uid(sid, id->uid);
 
        ret = True;
  done:
@@ -4947,8 +5084,151 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
        return ret;
 }
 
+/**
+ * Find the SID for a uid.
+ * This is shortcut is only used if ldapsam:trusted is set to true.
+ */
+static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid,
+                              struct dom_sid *sid)
+{
+       struct ldapsam_privates *priv =
+               (struct ldapsam_privates *)methods->private_data;
+       char *filter;
+       const char *attrs[] = { "sambaSID", NULL };
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       bool ret = false;
+       char *user_sid_string;
+       struct dom_sid user_sid;
+       int rc;
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+
+       filter = talloc_asprintf(tmp_ctx,
+                                "(&(uidNumber=%u)"
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                (unsigned int)uid,
+                                LDAP_OBJ_POSIXACCOUNT,
+                                LDAP_OBJ_SAMBASAMACCOUNT);
+       if (filter == NULL) {
+               DEBUG(3, ("talloc_asprintf failed\n"));
+               goto done;
+       }
+
+       rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result);
+       if (rc != LDAP_SUCCESS) {
+               goto done;
+       }
+       talloc_autofree_ldapmsg(tmp_ctx, result);
+
+       if (ldap_count_entries(priv2ld(priv), result) != 1) {
+               DEBUG(3, ("ERROR: Got %d entries for uid %u, expected one\n",
+                          ldap_count_entries(priv2ld(priv), result),
+                          (unsigned int)uid));
+               goto done;
+       }
+
+       entry = ldap_first_entry(priv2ld(priv), result);
+
+       user_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                                         "sambaSID", tmp_ctx);
+       if (user_sid_string == NULL) {
+               DEBUG(1, ("Could not find sambaSID in object '%s'\n",
+                         smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry)));
+               goto done;
+       }
+
+       if (!string_to_sid(&user_sid, user_sid_string)) {
+               DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
+                         user_sid_string));
+               goto done;
+       }
+
+       sid_copy(sid, &user_sid);
+
+       store_uid_sid_cache(sid, uid);
+       idmap_cache_set_sid2uid(sid, uid);
+
+       ret = true;
+
+ done:
+       TALLOC_FREE(tmp_ctx);
+       return ret;
+}
+
+/**
+ * Find the SID for a gid.
+ * This is shortcut is only used if ldapsam:trusted is set to true.
+ */
+static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
+                              struct dom_sid *sid)
+{
+       struct ldapsam_privates *priv =
+               (struct ldapsam_privates *)methods->private_data;
+       char *filter;
+       const char *attrs[] = { "sambaSID", NULL };
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       bool ret = false;
+       char *group_sid_string;
+       struct dom_sid group_sid;
+       int rc;
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+
+       filter = talloc_asprintf(tmp_ctx,
+                                "(&(gidNumber=%u)"
+                                "(objectClass=%s))",
+                                (unsigned int)gid,
+                                LDAP_OBJ_GROUPMAP);
+       if (filter == NULL) {
+               DEBUG(3, ("talloc_asprintf failed\n"));
+               goto done;
+       }
+
+       rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result);
+       if (rc != LDAP_SUCCESS) {
+               goto done;
+       }
+       talloc_autofree_ldapmsg(tmp_ctx, result);
+
+       if (ldap_count_entries(priv2ld(priv), result) != 1) {
+               DEBUG(3, ("ERROR: Got %d entries for gid %u, expected one\n",
+                          ldap_count_entries(priv2ld(priv), result),
+                          (unsigned int)gid));
+               goto done;
+       }
+
+       entry = ldap_first_entry(priv2ld(priv), result);
+
+       group_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                                         "sambaSID", tmp_ctx);
+       if (group_sid_string == NULL) {
+               DEBUG(1, ("Could not find sambaSID in object '%s'\n",
+                         smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry)));
+               goto done;
+       }
+
+       if (!string_to_sid(&group_sid, group_sid_string)) {
+               DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
+                         group_sid_string));
+               goto done;
+       }
+
+       sid_copy(sid, &group_sid);
+
+       store_gid_sid_cache(sid, gid);
+       idmap_cache_set_sid2gid(sid, gid);
+
+       ret = true;
+
+ done:
+       TALLOC_FREE(tmp_ctx);
+       return ret;
+}
+
+
 /*
- * The following functions is called only if
+ * The following functions are called only if
  * ldapsam:trusted and ldapsam:editposix are
  * set to true
  */
@@ -4963,12 +5243,12 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
 
 static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                                    TALLOC_CTX *tmp_ctx, const char *name,
-                                   uint32 acb_info, uint32 *rid)
+                                   uint32_t acb_info, uint32_t *rid)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAPMessage *entry = NULL;
        LDAPMessage *result = NULL;
-       uint32 num_result;
+       uint32_t num_result;
        bool is_machine = False;
        bool add_posix = False;
        LDAPMod **mods = NULL;
@@ -4980,8 +5260,8 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
        char *uidstr;
        char *shell;
        const char *dn = NULL;
-       DOM_SID group_sid;
-       DOM_SID user_sid;
+       struct dom_sid group_sid;
+       struct dom_sid user_sid;
        gid_t gid = -1;
        uid_t uid = -1;
        NTSTATUS ret;
@@ -4994,10 +5274,10 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                is_machine = True;
        }
 
-       username = escape_ldap_string_alloc(name);
+       username = escape_ldap_string(talloc_tos(), name);
        filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))",
                                 username, LDAP_OBJ_POSIXACCOUNT);
-       SAFE_FREE(username);
+       TALLOC_FREE(username);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
        if (rc != LDAP_SUCCESS) {
@@ -5088,7 +5368,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (!init_ldap_from_sam(ldap_state, NULL, &mods, user, element_is_set_or_changed)) {
+       if (!init_ldap_from_sam(ldap_state, entry, &mods, user, pdb_element_is_set_or_changed)) {
                DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -5104,7 +5384,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
 
                /* retrieve the Domain Users group gid */
-               if (!sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS) ||
+               if (!sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_RID_USERS) ||
                    !sid_to_gid(&group_sid, &gid)) {
                        DEBUG (0, ("ldapsam_create_user: Unable to get the Domain Users gid: bailing out!\n"));
                        return NT_STATUS_INVALID_PRIMARY_GROUP;
@@ -5230,6 +5510,40 @@ static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *
                return NT_STATUS_NO_MEMORY;
        }
 
+       /* try to remove memberships first */
+       {
+               NTSTATUS status;
+               struct dom_sid *sids = NULL;
+               gid_t *gids = NULL;
+               uint32_t num_groups = 0;
+               int i;
+               uint32_t user_rid = pdb_get_user_rid(sam_acct);
+
+               status = ldapsam_enum_group_memberships(my_methods,
+                                                       tmp_ctx,
+                                                       sam_acct,
+                                                       &sids,
+                                                       &gids,
+                                                       &num_groups);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto delete_dn;
+               }
+
+               for (i=0; i < num_groups; i++) {
+
+                       uint32_t group_rid;
+
+                       sid_peek_rid(&sids[i], &group_rid);
+
+                       ldapsam_del_groupmem(my_methods,
+                                            tmp_ctx,
+                                            group_rid,
+                                            user_rid);
+               }
+       }
+
+ delete_dn:
+
        rc = smbldap_delete(ldap_state->smbldap_state, dn);
        if (rc != LDAP_SUCCESS) {
                return NT_STATUS_UNSUCCESSFUL;
@@ -5251,13 +5565,13 @@ static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *
 static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                                         TALLOC_CTX *tmp_ctx,
                                         const char *name,
-                                        uint32 *rid)
+                                        uint32_t *rid)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        NTSTATUS ret;
        LDAPMessage *entry = NULL;
        LDAPMessage *result = NULL;
-       uint32 num_result;
+       uint32_t num_result;
        bool is_new_entry = False;
        LDAPMod **mods = NULL;
        char *filter;
@@ -5266,14 +5580,14 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        char *grouptype;
        char *gidstr;
        const char *dn = NULL;
-       DOM_SID group_sid;
+       struct dom_sid group_sid;
        gid_t gid = -1;
        int rc;
 
-       groupname = escape_ldap_string_alloc(name);
+       groupname = escape_ldap_string(talloc_tos(), name);
        filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
                                 groupname, LDAP_OBJ_POSIXGROUP);
-       SAFE_FREE(groupname);
+       TALLOC_FREE(groupname);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
        if (rc != LDAP_SUCCESS) {
@@ -5323,12 +5637,35 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        }
 
        if (num_result == 0) {
+               is_new_entry = true;
+       }
+
+       if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
+               DEBUG(1, ("ldapsam_create_group: Could not allocate a new RID\n"));
+               return ret;
+       }
+
+       sid_compose(&group_sid, get_global_sam_sid(), *rid);
+
+       groupsidstr = talloc_strdup(tmp_ctx, sid_string_talloc(tmp_ctx,
+                                                              &group_sid));
+       grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
+
+       if (!groupsidstr || !grouptype) {
+               DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
+
+       if (is_new_entry) {
                char *escape_name;
 
                DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
 
-               is_new_entry = True;
-
                /* lets allocate a new groupid for this group */
                if (!winbind_allocate_gid(&gid)) {
                        DEBUG (0, ("ldapsam_create_group: Unable to allocate a new group id: bailing out!\n"));
@@ -5357,26 +5694,6 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
        }
 
-       if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
-               DEBUG(1, ("ldapsam_create_group: Could not allocate a new RID\n"));
-               return ret;
-       }
-
-       sid_compose(&group_sid, get_global_sam_sid(), *rid);
-
-       groupsidstr = talloc_strdup(tmp_ctx, sid_string_talloc(tmp_ctx,
-                                                              &group_sid));
-       grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
-
-       if (!groupsidstr || !grouptype) {
-               DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
        talloc_autofree_ldapmod(tmp_ctx, mods);
 
        if (is_new_entry) {     
@@ -5403,7 +5720,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, uint32 rid)
+static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, uint32_t rid)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAPMessage *result = NULL;
@@ -5412,7 +5729,7 @@ static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_
        const char *dn;
        char *gidstr;
        char *filter;
-       DOM_SID group_sid;
+       struct dom_sid group_sid;
        int rc;
 
        /* get the group sid */
@@ -5499,20 +5816,20 @@ static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_
 
 static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
                                        TALLOC_CTX *tmp_ctx,
-                                       uint32 group_rid,
-                                       uint32 member_rid,
+                                       uint32_t group_rid,
+                                       uint32_t member_rid,
                                        int modop)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAPMessage *entry = NULL;
        LDAPMessage *result = NULL;
-       uint32 num_result;
+       uint32_t num_result;
        LDAPMod **mods = NULL;
        char *filter;
        char *uidstr;
        const char *dn = NULL;
-       DOM_SID group_sid;
-       DOM_SID member_sid;
+       struct dom_sid group_sid;
+       struct dom_sid member_sid;
        int rc;
 
        switch (modop) {
@@ -5661,15 +5978,15 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
 
 static NTSTATUS ldapsam_add_groupmem(struct pdb_methods *my_methods,
                                     TALLOC_CTX *tmp_ctx,
-                                    uint32 group_rid,
-                                    uint32 member_rid)
+                                    uint32_t group_rid,
+                                    uint32_t member_rid)
 {
        return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_ADD);
 }
 static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
                                     TALLOC_CTX *tmp_ctx,
-                                    uint32 group_rid,
-                                    uint32 member_rid)
+                                    uint32_t group_rid,
+                                    uint32_t member_rid)
 {
        return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_DELETE);
 }
@@ -5681,7 +5998,7 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAPMessage *entry = NULL;
        LDAPMessage *result = NULL;
-       uint32 num_result;
+       uint32_t num_result;
        LDAPMod **mods = NULL;
        char *filter;
        char *escape_username;
@@ -5702,7 +6019,8 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
                return NT_STATUS_NO_MEMORY;
        }
 
-       escape_username = escape_ldap_string_alloc(pdb_get_username(sampass));
+       escape_username = escape_ldap_string(talloc_tos(),
+                                            pdb_get_username(sampass));
        if (escape_username== NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -5715,7 +6033,7 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
                                 LDAP_OBJ_POSIXACCOUNT,
                                 LDAP_OBJ_SAMBASAMACCOUNT);
 
-       SAFE_FREE(escape_username);
+       TALLOC_FREE(escape_username);
 
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
@@ -5795,7 +6113,7 @@ static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
        int attrsonly = 0; /* 0: return values too */
        LDAPMessage *result = NULL;
        char *trusted_dn;
-       uint32 num_result;
+       uint32_t num_result;
 
        filter = talloc_asprintf(talloc_tos(),
                                 "(&(objectClass=%s)(sambaDomainName=%s))",
@@ -5845,7 +6163,7 @@ static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
 static bool ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
                                      const char *domain,
                                      char** pwd,
-                                     DOM_SID *sid,
+                                     struct dom_sid *sid,
                                      time_t *pass_last_set_time)
 {
        struct ldapsam_privates *ldap_state =
@@ -5889,18 +6207,17 @@ static bool ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
        /* domain sid */
        if (sid != NULL) {
                char *sid_str;
-               DOM_SID *dom_sid;
+               struct dom_sid dom_sid;
                sid_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
                                                          entry, "sambaSID",
                                                          talloc_tos());
                if (sid_str == NULL) {
                        return False;
                }
-               dom_sid = string_sid_talloc(talloc_tos(), sid_str);
-               if (dom_sid == NULL) {
+               if (!string_to_sid(&dom_sid, sid_str)) {
                        return False;
                }
-               sid_copy(sid, dom_sid);
+               sid_copy(sid, &dom_sid);
        }
 
        return True;
@@ -5909,7 +6226,7 @@ static bool ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
 static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
                                      const char* domain,
                                      const char* pwd,
-                                     const DOM_SID *sid)
+                                     const struct dom_sid *sid)
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
@@ -5941,8 +6258,6 @@ static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
                         "sambaClearTextPassword", pwd);
 
-       talloc_autofree_ldapmod(talloc_tos(), mods);
-
        if (entry != NULL) {
                prev_pwd = smbldap_talloc_single_attribute(priv2ld(ldap_state),
                                entry, "sambaClearTextPassword", talloc_tos());
@@ -5953,6 +6268,8 @@ static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
                }
        }
 
+       talloc_autofree_ldapmod(talloc_tos(), mods);
+
        trusted_dn = trusteddom_dn(ldap_state, domain);
        if (trusted_dn == NULL) {
                return False;
@@ -6007,7 +6324,7 @@ static bool ldapsam_del_trusteddom_pw(struct pdb_methods *methods,
 
 static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
                                         TALLOC_CTX *mem_ctx,
-                                        uint32 *num_domains,
+                                        uint32_t *num_domains,
                                         struct trustdom_info ***domains)
 {
        int rc;
@@ -6040,7 +6357,7 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
        }
 
        *num_domains = 0;
-       if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
+       if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *, 1))) {
                DEBUG(1, ("talloc failed\n"));
                return NT_STATUS_NO_MEMORY;
        }
@@ -6052,7 +6369,7 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
                char *dom_name, *dom_sid_str;
                struct trustdom_info *dom_info;
 
-               dom_info = TALLOC_P(*domains, struct trustdom_info);
+               dom_info = talloc(*domains, struct trustdom_info);
                if (dom_info == NULL) {
                        DEBUG(1, ("talloc failed\n"));
                        return NT_STATUS_NO_MEMORY;
@@ -6154,7 +6471,7 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
 
        (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
 
-       (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
+       (*pdb_method)->capabilities = ldapsam_capabilities;
        (*pdb_method)->new_rid = ldapsam_new_rid;
 
        (*pdb_method)->get_trusteddom_pw = ldapsam_get_trusteddom_pw;
@@ -6164,7 +6481,7 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
 
        /* TODO: Setup private data and free */
 
-       if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
+       if ( !(ldap_state = talloc_zero(*pdb_method, struct ldapsam_privates)) ) {
                DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
                return NT_STATUS_NO_MEMORY;
        }
@@ -6224,21 +6541,20 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
 {
        NTSTATUS nt_status;
        struct ldapsam_privates *ldap_state = NULL;
-       uint32 alg_rid_base;
+       uint32_t alg_rid_base;
        char *alg_rid_base_string = NULL;
        LDAPMessage *result = NULL;
        LDAPMessage *entry = NULL;
-       DOM_SID ldap_domain_sid;
-       DOM_SID secrets_domain_sid;
+       struct dom_sid ldap_domain_sid;
+       struct dom_sid secrets_domain_sid;
        char *domain_sid_string = NULL;
        char *dn = NULL;
        char *uri = talloc_strdup( NULL, location );
 
        trim_char( uri, '\"', '\"' );
        nt_status = pdb_init_ldapsam_common(pdb_method, uri);
-       if (uri) {
-               TALLOC_FREE(uri);
-       }
+
+       TALLOC_FREE(uri);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
@@ -6260,6 +6576,8 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                        ldapsam_enum_group_memberships;
                (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
                (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
+               (*pdb_method)->uid_to_sid = ldapsam_uid_to_sid;
+               (*pdb_method)->gid_to_sid = ldapsam_gid_to_sid;
 
                if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
                        (*pdb_method)->create_user = ldapsam_create_user;
@@ -6282,13 +6600,10 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                                               ldap_state->domain_name, True);
 
        if ( !NT_STATUS_IS_OK(nt_status) ) {
-               DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
-                         "info, nor add one to the domain\n"));
-               DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
-                            "will be unable to allocate new users/groups, "
-                            "and will risk BDCs having inconsistant SIDs\n"));
-               sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
-               return NT_STATUS_OK;
+               DEBUG(0, ("pdb_init_ldapsam: WARNING: Could not get domain "
+                         "info, nor add one to the domain. "
+                         "We cannot work reliably without it.\n"));
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
        /* Given that the above might fail, everything below this must be
@@ -6330,7 +6645,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                }
                found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
                                                     &secrets_domain_sid);
-               if (!found_sid || !sid_equal(&secrets_domain_sid,
+               if (!found_sid || !dom_sid_equal(&secrets_domain_sid,
                                             &ldap_domain_sid)) {
                        DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
                                  "%s based on pdb_ldap results %s -> %s\n",
@@ -6355,7 +6670,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                                         LDAP_ATTR_ALGORITHMIC_RID_BASE ),
                    talloc_tos());
        if (alg_rid_base_string) {
-               alg_rid_base = (uint32)atol(alg_rid_base_string);
+               alg_rid_base = (uint32_t)atol(alg_rid_base_string);
                if (alg_rid_base != algorithmic_rid_base()) {
                        DEBUG(0, ("The value of 'algorithmic RID base' has "
                                  "changed since the LDAP\n"
@@ -6383,5 +6698,7 @@ NTSTATUS pdb_ldap_init(void)
        /* Let pdb_nds register backends */
        pdb_nds_init();
 
+       pdb_ipa_init();
+
        return NT_STATUS_OK;
 }