s3-passdb Make pdb_element_is_changed available to all passdb modules
[idra/samba.git] / source3 / passdb / pdb_ldap.c
index f031483ea1596eba50a844123535c02377896df2..74dcceca4ee481daab38e863347c25e424d97481 100644 (file)
@@ -7,20 +7,20 @@
    Copyright (C) Andrew Bartlett               2002-2003
    Copyright (C) Stefan (metze) Metzmacher     2002-2003
    Copyright (C) Simo Sorce                    2006
-    
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   
+
 */
 
 /* TODO:
 */
 
 #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"
 
@@ -83,7 +65,7 @@
  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;
 }
@@ -97,10 +79,10 @@ static const char* get_userattr_key2string( int schema_ver, int key )
        switch ( schema_ver ) {
                case SCHEMAVER_SAMBAACCOUNT:
                        return get_attr_key2string( attrib_map_v22, key );
-                       
+
                case SCHEMAVER_SAMBASAMACCOUNT:
                        return get_attr_key2string( attrib_map_v30, key );
-                       
+
                default:
                        DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
                        break;
@@ -117,14 +99,14 @@ const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
        switch ( schema_ver ) {
                case SCHEMAVER_SAMBAACCOUNT:
                        return get_attr_list( mem_ctx, attrib_map_v22 );
-                       
+
                case SCHEMAVER_SAMBASAMACCOUNT:
                        return get_attr_list( mem_ctx, attrib_map_v30 );
                default:
                        DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
                        break;
        }
-       
+
        return NULL;
 }
 
@@ -139,7 +121,7 @@ static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
                case SCHEMAVER_SAMBAACCOUNT:
                        return get_attr_list( mem_ctx,
                                              attrib_map_to_delete_v22 );
-                       
+
                case SCHEMAVER_SAMBASAMACCOUNT:
                        return get_attr_list( mem_ctx,
                                              attrib_map_to_delete_v30 );
@@ -147,7 +129,7 @@ static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
                        DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
                        break;
        }
-       
+
        return NULL;
 }
 
@@ -161,7 +143,7 @@ static const char* get_objclass_filter( int schema_ver )
 {
        fstring objclass_filter;
        char *result;
-       
+
        switch( schema_ver ) {
                case SCHEMAVER_SAMBAACCOUNT:
                        fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
@@ -174,7 +156,7 @@ static const char* get_objclass_filter( int schema_ver )
                        objclass_filter[0] = '\0';
                        break;
        }
-       
+
        result = talloc_strdup(talloc_tos(), objclass_filter);
        SMB_ASSERT(result != NULL);
        return result;
@@ -226,7 +208,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;
        }
@@ -335,7 +317,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) {
@@ -349,7 +331,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;
        }
        /*
@@ -359,7 +341,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;
        }
@@ -375,7 +357,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;
@@ -398,7 +380,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;
@@ -447,7 +429,7 @@ static int ldapsam_delete_entry(struct ldapsam_privates *priv,
        }
 
        /* Ok, delete only the SAM attributes */
-       
+
        for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
             name != NULL;
             name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
@@ -528,19 +510,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");
@@ -559,7 +541,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                goto fn_exit;
        }
 
-       if (!(username = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+       if (!(username = smbldap_talloc_first_attribute(priv2ld(ldap_state),
                                        entry,
                                        "uid",
                                        ctx))) {
@@ -603,12 +585,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),
@@ -840,27 +822,27 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
                /* Make call to Novell eDirectory ldap extension to get clear text password.
                        NOTE: This will only work if we have an SSL connection to eDirectory. */
-               user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+               user_dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry);
                if (user_dn != NULL) {
-                       DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn));
+                       DEBUG(3, ("init_sam_from_ldap: smbldap_talloc_dn(ctx, %s) returned '%s'\n", username, user_dn));
 
                        pwd_len = sizeof(clear_text_pw);
                        if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
                                nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
                                if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
-                                       SAFE_FREE(user_dn);
+                                       TALLOC_FREE(user_dn);
                                        return False;
                                }
                                ZERO_STRUCT(smblmpwd);
                                if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
-                                       SAFE_FREE(user_dn);
+                                       TALLOC_FREE(user_dn);
                                        return False;
                                }
                                ZERO_STRUCT(smbntpwd);
                                use_samba_attrs = False;
                        }
 
-                       SAFE_FREE(user_dn);
+                       TALLOC_FREE(user_dn);
 
                } else {
                        DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
@@ -901,11 +883,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) {
@@ -914,9 +896,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;
                }
@@ -984,7 +966,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);
        }
@@ -1008,7 +990,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);
        }
 
@@ -1023,11 +1005,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,
@@ -1035,8 +1028,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);
                }
        }
 
@@ -1048,7 +1101,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)));
@@ -1058,10 +1111,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 */
@@ -1070,13 +1123,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);
        }
 
@@ -1085,7 +1138,6 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
   fn_exit:
 
        TALLOC_FREE(ctx);
-       SAFE_FREE(cache_entry);
        return ret;
 }
 
@@ -1101,7 +1153,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"));
@@ -1130,7 +1182,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:
@@ -1167,7 +1219,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:
@@ -1249,7 +1301,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), 
                        pdb_get_profile_path(sampass));
 
-       if (asprintf(&temp, "%li", pdb_get_logon_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_logon_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_LOGONTIME))
@@ -1257,7 +1309,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_logoff_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_logoff_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_LOGOFFTIME))
@@ -1265,7 +1317,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_kickoff_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_kickoff_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_KICKOFFTIME))
@@ -1273,7 +1325,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_pass_can_change_time_noncalc(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_pass_can_change_time_noncalc(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_CANCHANGETIME))
@@ -1281,7 +1333,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_pass_must_change_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_pass_must_change_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_MUSTCHANGETIME))
@@ -1325,8 +1377,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) {
@@ -1338,7 +1390,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. */
@@ -1361,7 +1413,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
                if (need_update(sampass, PDB_PASSLASTSET)) {
                        if (asprintf(&temp, "%li",
-                               pdb_get_pass_last_set_time(sampass)) < 0) {
+                               (long int)pdb_get_pass_last_set_time(sampass)) < 0) {
                                return false;
                        }
                        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
@@ -1400,10 +1452,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));
@@ -1423,7 +1475,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                                temp);
                        SAFE_FREE(temp);
 
-                       if (asprintf(&temp, "%li", badtime) < 0) {
+                       if (asprintf(&temp, "%li", (long int)badtime) < 0) {
                                return false;
                        }
                        smbldap_make_mod(
@@ -1439,7 +1491,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);
@@ -1447,7 +1499,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);
                }
        }
 
@@ -1480,13 +1532,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.
 *********************************************************************/
@@ -1500,21 +1562,21 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu
        int count;
        const char ** attr_list;
        int rc;
-       
+
        attr_list = get_userattr_list( user, ldap_state->schema_ver );
        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 );
 
        if ( rc != LDAP_SUCCESS ) 
                return NT_STATUS_NO_SUCH_USER;
-       
+
        count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-       
+
        if (count < 1) {
                DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count));
                ldap_msgfree(result);
@@ -1543,11 +1605,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: {
@@ -1562,7 +1624,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);
@@ -1571,12 +1633,12 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
                                return rc;
                        break;
                }
-                       
+
                case SCHEMAVER_SAMBAACCOUNT:
                        if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
                                return rc;
                        }
-               
+
                        attr_list = get_userattr_list(NULL,
                                                      ldap_state->schema_ver);
                        rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
@@ -1593,7 +1655,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;
@@ -1607,7 +1669,7 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu
                return NT_STATUS_NO_SUCH_USER;
 
        count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-       
+
        if (count < 1) {
                DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] "
                          "count=%d\n", sid_string_dbg(sid), count));
@@ -1651,44 +1713,11 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        int rc;
-       
+
        if (!newpwd || !dn) {
                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) &&
@@ -1700,6 +1729,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) {
 
@@ -1711,46 +1741,63 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                        }
                }
 
-               if (!push_utf8_allocate(&utf8_password,
+               if (!push_utf8_talloc(talloc_tos(), &utf8_password,
                                        pdb_get_plaintext_passwd(newpwd),
                                        &converted_size))
                {
                        return NT_STATUS_NO_MEMORY;
                }
 
-               if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) {
-                       SAFE_FREE(utf8_password);
+               if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
+                       TALLOC_FREE(utf8_password);
                        return NT_STATUS_NO_MEMORY;
                }
 
                if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
                        DEBUG(0,("ber_alloc_t returns NULL\n"));
-                       SAFE_FREE(utf8_password);
-                       SAFE_FREE(utf8_dn);
+                       TALLOC_FREE(utf8_password);
+                       TALLOC_FREE(utf8_dn);
                        return NT_STATUS_UNSUCCESSFUL;
                }
 
                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);
-                       SAFE_FREE(utf8_dn);
-                       SAFE_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) {
                        DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
                        ber_free(ber,1);
-                       SAFE_FREE(utf8_dn);
-                       SAFE_FREE(utf8_password);
+                       TALLOC_FREE(utf8_dn);
+                       TALLOC_FREE(utf8_password);
                        return NT_STATUS_UNSUCCESSFUL;
                }
-               
-               SAFE_FREE(utf8_dn);
-               SAFE_FREE(utf8_password);
+
+               TALLOC_FREE(utf8_dn);
+               TALLOC_FREE(utf8_password);
                ber_free(ber, 1);
 
                if (!ldap_state->is_nds_ldap) {
@@ -1796,6 +1843,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;
 }
 
@@ -1845,7 +1926,7 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
                result = NT_STATUS_NO_SUCH_USER;
                goto done;
        }
-       
+
        rc = ldapsam_delete_entry(
                priv, mem_ctx, entry,
                priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
@@ -1860,17 +1941,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.
 *********************************************************************/
@@ -1908,7 +1978,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
        }
 
        entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
-       dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+       dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
        if (!dn) {
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -1916,9 +1986,9 @@ 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"));
-               SAFE_FREE(dn);
+               TALLOC_FREE(dn);
                if (mods != NULL)
                        ldap_mods_free(mods,True);
                return NT_STATUS_UNSUCCESSFUL;
@@ -1928,17 +1998,17 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
            && (mods == NULL)) {
                DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
                         pdb_get_username(newpwd)));
-               SAFE_FREE(dn);
+               TALLOC_FREE(dn);
                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);
        }
 
-       SAFE_FREE(dn);
+       TALLOC_FREE(dn);
 
        /*
         * We need to set the backend private data to NULL here. For example
@@ -1967,6 +2037,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)
@@ -2039,18 +2121,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.
 *********************************************************************/
@@ -2064,11 +2134,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;
@@ -2101,7 +2171,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) {
@@ -2119,18 +2189,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);
@@ -2147,17 +2217,10 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
 
        /* Check if we need to update an existing entry */
        if (num_result == 1) {
-               char *tmp;
-
                DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
                ldap_op = LDAP_MOD_REPLACE;
                entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
-               tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
-               if (!tmp) {
-                       goto fn_exit;
-               }
-               dn = talloc_asprintf(ctx, "%s", tmp);
-               SAFE_FREE(tmp);
+               dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry);
                if (!dn) {
                        status = NT_STATUS_NO_MEMORY;
                        goto fn_exit;
@@ -2200,17 +2263,11 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
 
                /* Check if we need to update an existing entry */
                if (num_result == 1) {
-                       char *tmp;
 
                        DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
                        ldap_op = LDAP_MOD_REPLACE;
                        entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
-                       tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
-                       if (!tmp) {
-                               goto fn_exit;
-                       }
-                       dn = talloc_asprintf(ctx, "%s", tmp);
-                       SAFE_FREE(tmp);
+                       dn = smbldap_talloc_dn (ctx, ldap_state->smbldap_state->ldap_struct, entry);
                        if (!dn) {
                                status = NT_STATUS_NO_MEMORY;
                                goto fn_exit;
@@ -2250,7 +2307,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);
@@ -2274,7 +2331,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));
@@ -2290,7 +2347,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);
        }
@@ -2310,7 +2366,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);
 
@@ -2432,6 +2488,7 @@ for gidNumber(%lu)\n",(unsigned long)map->gid));
 
        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);
@@ -2494,7 +2551,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;
@@ -2540,7 +2597,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) {
@@ -2552,11 +2609,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;
@@ -2564,11 +2621,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)) {
@@ -2581,7 +2638,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;
@@ -2597,8 +2654,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 =
@@ -2630,7 +2687,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);
 
@@ -2666,7 +2723,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) {
@@ -2677,20 +2734,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, "))");
@@ -2716,8 +2772,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",
@@ -2768,7 +2824,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,7 +2843,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
        }
 
        ret = NT_STATUS_OK;
-       
+
  done:
 
        if (values)
@@ -2799,9 +2855,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;
@@ -2813,7 +2869,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;
 
@@ -2824,61 +2881,65 @@ 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,
-                                "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%d)))",
-                                LDAP_OBJ_POSIXGROUP, escape_name, primary_gid);
+                                "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%u)))",
+                                LDAP_OBJ_POSIXGROUP, escape_name, (unsigned int)primary_gid);
        if (filter == NULL) {
                ret = NT_STATUS_NO_MEMORY;
                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)
@@ -2912,7 +2973,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;
 
@@ -2950,7 +3011,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;
@@ -2962,7 +3023,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
  done:
 
-       SAFE_FREE(escape_name);
+       TALLOC_FREE(escape_name);
        return ret;
 }
 
@@ -2981,7 +3042,7 @@ static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
 
        filter = talloc_asprintf(mem_ctx,
                                 "(&(objectClass=%s)(gidNumber=%u))",
-                                LDAP_OBJ_POSIXGROUP, map->gid);
+                                LDAP_OBJ_POSIXGROUP, (unsigned int)map->gid);
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -3037,7 +3098,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;
 
@@ -3104,8 +3165,8 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
        }
 
        if (pdb_gid_to_sid(map->gid, &sid)) {
-               DEBUG(3, ("Gid %d is already mapped to SID %s, refusing to "
-                         "add\n", map->gid, sid_string_dbg(&sid)));
+               DEBUG(3, ("Gid %u is already mapped to SID %s, refusing to "
+                         "add\n", (unsigned int)map->gid, sid_string_dbg(&sid)));
                result = NT_STATUS_GROUP_EXISTS;
                goto done;
        }
@@ -3136,7 +3197,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
                         map->comment);
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
-                        talloc_asprintf(mem_ctx, "%u", map->gid));
+                        talloc_asprintf(mem_ctx, "%u", (unsigned int)map->gid));
        talloc_autofree_ldapmod(mem_ctx, mods);
 
        rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
@@ -3182,7 +3243,7 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
                                 "(sambaGroupType=%d))",
                                 LDAP_OBJ_GROUPMAP,
                                 sid_string_talloc(mem_ctx, &map->sid),
-                                map->gid, map->sid_name_use);
+                                (unsigned int)map->gid, map->sid_name_use);
        if (filter == NULL) {
                result = NT_STATUS_NO_MEMORY;
                goto done;
@@ -3242,7 +3303,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;
@@ -3280,8 +3341,9 @@ static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
        rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
                                  get_attr_list(mem_ctx,
                                                groupmap_attr_list_to_delete));
+
        if ((rc == LDAP_NAMING_VIOLATION) ||
+           (rc == LDAP_NOT_ALLOWED_ON_RDN) ||
            (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
                const char *attrs[] = { "sambaGroupType", "description",
                                        "displayName", "sambaSIDList",
@@ -3296,6 +3358,7 @@ static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
        }
 
        if ((rc == LDAP_NAMING_VIOLATION) ||
+           (rc == LDAP_NOT_ALLOWED_ON_RDN) ||
            (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
                const char *attrs[] = { "sambaGroupType", "description",
                                        "displayName", "sambaSIDList",
@@ -3334,7 +3397,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);
@@ -3343,7 +3406,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);
@@ -3386,11 +3449,11 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
        while (!bret) {
                if (!ldap_state->entry)
                        return ret;
-               
+
                ldap_state->index++;
                bret = init_group_from_ldap(ldap_state, map,
                                            ldap_state->entry);
-               
+
                ldap_state->entry =
                        ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
                                        ldap_state->entry);     
@@ -3403,12 +3466,12 @@ 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,
+                                          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 = { 0, };
        size_t entries = 0;
 
        *p_num_entries = 0;
@@ -3453,8 +3516,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 =
@@ -3525,7 +3588,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+       dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
        if (!dn) {
                ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
@@ -3540,7 +3603,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
 
        ldap_mods_free(mods, True);
        ldap_msgfree(result);
-       SAFE_FREE(dn);
+       TALLOC_FREE(dn);
 
        if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
                return NT_STATUS_MEMBER_IN_ALIAS;
@@ -3558,23 +3621,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,
-                                     DOM_SID **pp_members,
+                                     const struct dom_sid *alias,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct dom_sid **pp_members,
                                      size_t *p_num_members)
 {
        struct ldapsam_privates *ldap_state =
@@ -3585,7 +3649,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;
 
@@ -3660,13 +3724,13 @@ 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]))
                        continue;
 
-               status = add_sid_to_array(NULL, &member, pp_members,
+               status = add_sid_to_array(mem_ctx, &member, pp_members,
                                          &num_members);
                if (!NT_STATUS_IS_OK(status)) {
                        ldap_value_free(values);
@@ -3684,10 +3748,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 =
@@ -3702,8 +3766,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;
        }
 
@@ -3717,8 +3787,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++)
@@ -3733,11 +3807,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;
 
@@ -3746,8 +3829,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,
@@ -3761,20 +3844,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;
@@ -3791,7 +3884,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"));
@@ -3811,7 +3904,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;
@@ -3821,15 +3914,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;
@@ -3837,6 +3931,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 =
@@ -3850,20 +3945,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;
        }
@@ -3883,8 +3982,8 @@ 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;
 
 out:
@@ -3899,7 +3998,7 @@ out:
 
    - if user hasn't decided to use account policies inside LDAP just reuse the
      old tdb values
-   
+
    - if there is a valid cache entry, return that
    - if there is an LDAP entry, update cache and return 
    - otherwise set to default, update cache and return
@@ -3907,17 +4006,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;
@@ -3928,27 +4028,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;
@@ -3958,9 +4058,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)
 {
@@ -3987,6 +4087,11 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                goto done;
        }
 
+       if (num_rids == 0) {
+               result = NT_STATUS_NONE_MAPPED;
+               goto done;
+       }
+
        for (i=0; i<num_rids; i++)
                attrs[i] = SID_NAME_UNKNOWN;
 
@@ -3996,7 +4101,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)",
@@ -4036,7 +4141,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;
 
@@ -4089,7 +4194,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);
@@ -4110,7 +4215,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;
@@ -4189,19 +4294,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;
@@ -4212,7 +4317,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;
        }
 
@@ -4221,6 +4326,7 @@ const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
                result[i] = talloc_strdup(result, va_arg(ap, const char*));
                if (result[i] == NULL) {
                        talloc_free(result);
+                       va_end(ap);
                        return NULL;
                }
        }
@@ -4233,8 +4339,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;
@@ -4295,11 +4401,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;
 }
 
@@ -4328,6 +4429,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;
@@ -4348,7 +4450,12 @@ static bool ldapsam_search_next_entry(struct pdb_search *search,
            !ldapsam_search_nextpage(search))
                    return False;
 
-       result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct,
+       if (state->current_entry == NULL) {
+               return false;
+       }
+
+       result = state->ldap2displayentry(state, search,
+                                         state->connection->ldap_struct,
                                          state->current_entry, entry);
 
        if (!result) {
@@ -4408,8 +4515,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)) {
@@ -4434,7 +4541,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",
@@ -4447,7 +4554,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",
@@ -4460,7 +4567,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",
@@ -4475,7 +4582,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
                DEBUG(0, ("talloc failed\n"));
                return False;
        }
-       
+
        vals = ldap_get_values(ld, entry, "sambaSid");
        if ((vals == NULL) || (vals[0] == NULL)) {
                DEBUG(0, ("\"objectSid\" not found\n"));
@@ -4501,13 +4608,13 @@ 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;
        struct ldap_search_state *state;
 
-       state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
+       state = talloc(search, struct ldap_search_state);
        if (state == NULL) {
                DEBUG(0, ("talloc failed\n"));
                return False;
@@ -4524,10 +4631,10 @@ static bool ldapsam_search_users(struct pdb_methods *methods,
                state->base = lp_ldap_suffix();
 
        state->acct_flags = acct_flags;
-       state->base = talloc_strdup(search->mem_ctx, state->base);
+       state->base = talloc_strdup(search, state->base);
        state->scope = LDAP_SCOPE_SUBTREE;
-       state->filter = get_ldap_filter(search->mem_ctx, "*");
-       state->attrs = talloc_attrs(search->mem_ctx, "uid", "sambaSid",
+       state->filter = get_ldap_filter(search, "*");
+       state->attrs = talloc_attrs(search, "uid", "sambaSid",
                                    "displayName", "description",
                                    "sambaAcctFlags", NULL);
        state->attrsonly = 0;
@@ -4554,8 +4661,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 = "";
@@ -4594,7 +4701,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))
                {
@@ -4603,7 +4710,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))
        {
@@ -4617,7 +4724,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",
@@ -4631,7 +4738,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                DEBUG(0, ("talloc failed\n"));
                return False;
        }
-       
+
        vals = ldap_get_values(ld, entry, "sambaSid");
        if ((vals == NULL) || (vals[0] == NULL)) {
                DEBUG(0, ("\"objectSid\" not found\n"));
@@ -4660,9 +4767,9 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                                return False;
                        }
                        break;
-       
+
                default:
-                       DEBUG(0,("unkown group type: %d\n", group_type));
+                       DEBUG(0,("unknown group type: %d\n", group_type));
                        return False;
        }
 
@@ -4673,7 +4780,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 =
@@ -4681,7 +4788,7 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods,
        struct ldap_search_state *state;
        fstring tmp;
 
-       state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
+       state = talloc(search, struct ldap_search_state);
        if (state == NULL) {
                DEBUG(0, ("talloc failed\n"));
                return False;
@@ -4689,15 +4796,14 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods,
 
        state->connection = ldap_state->smbldap_state;
 
-       state->base = talloc_strdup(search->mem_ctx, 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->mem_ctx,
-                                       "(&(objectclass=%s)"
+       state->filter = talloc_asprintf(search, "(&(objectclass=%s)"
                                        "(sambaGroupType=%d)(sambaSID=%s*))",
                                         LDAP_OBJ_GROUPMAP,
                                         type, sid_to_fstring(tmp, sid));
-       state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
+       state->attrs = talloc_attrs(search, "cn", "sambaSid",
                                    "displayName", "description",
                                    "sambaGroupType", NULL);
        state->attrsonly = 0;
@@ -4726,18 +4832,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;
 
@@ -4747,7 +4853,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;
@@ -4784,21 +4890,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);
        }
 
@@ -4833,7 +4939,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;
 
@@ -4855,14 +4961,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 =
@@ -4927,6 +5033,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;
        }
@@ -4943,6 +5051,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:
@@ -4950,8 +5060,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
  */
@@ -4966,12 +5219,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;
@@ -4983,13 +5236,13 @@ 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;
        int rc;
-       
+
        if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
              acb_info & ACB_WSTRUST ||
              acb_info & ACB_SVRTRUST ||
@@ -4997,10 +5250,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) {
@@ -5015,7 +5268,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                DEBUG (0, ("ldapsam_create_user: More than one user with name [%s] ?!\n", name));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
-       
+
        if (num_result == 1) {
                char *tmp;
                /* check if it is just a posix account.
@@ -5044,7 +5297,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
        if (num_result == 0) {
                add_posix = True;
        }
-       
+
        /* Create the basic samu structure and generate the mods for the ldap commit */
        if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
                DEBUG(1, ("ldapsam_create_user: Could not allocate a new RID\n"));
@@ -5091,7 +5344,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;
        }
@@ -5107,7 +5360,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;
@@ -5128,8 +5381,8 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                        homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), name, ldap_state->domain_name, uid, gid);
                        shell = talloc_sub_specified(tmp_ctx, lp_template_shell(), name, ldap_state->domain_name, uid, gid);
                }
-               uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
-               gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+               uidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)uid);
+               gidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)gid);
 
                escape_name = escape_rdn_val_string_alloc(name);
                if (!escape_name) {
@@ -5190,7 +5443,7 @@ static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *
        int rc;
 
        DEBUG(0,("ldapsam_delete_user: Attempt to delete user [%s]\n", pdb_get_username(sam_acct)));
-       
+
        filter = talloc_asprintf(tmp_ctx,
                                 "(&(uid=%s)"
                                 "(objectClass=%s)"
@@ -5233,6 +5486,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;
@@ -5254,13 +5541,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;
@@ -5269,14 +5556,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) {
@@ -5291,7 +5578,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                DEBUG (0, ("ldapsam_create_group: There exists more than one group with name [%s]: bailing out!\n", name));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
-       
+
        if (num_result == 1) {
                char *tmp;
                /* check if it is just a posix group.
@@ -5315,7 +5602,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                        DEBUG (1, ("ldapsam_create_group: Couldn't retrieve the gidNumber for [%s]?!?!\n", name));
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
                }
-               
+
                gid = strtoul(tmp, NULL, 10);
 
                dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
@@ -5326,19 +5613,42 @@ 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"));
                        return NT_STATUS_UNSUCCESSFUL;
                }
 
-               gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+               gidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)gid);
 
                escape_name = escape_rdn_val_string_alloc(name);
                if (!escape_name) {
@@ -5360,26 +5670,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) {     
@@ -5406,7 +5696,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;
@@ -5415,7 +5705,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 */
@@ -5502,20 +5792,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) {
@@ -5528,7 +5818,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
        default:
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        /* get member sid  */
        sid_compose(&member_sid, get_global_sam_sid(), member_rid);
 
@@ -5575,7 +5865,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
                /* check if we are trying to remove the member from his primary group */
                char *gidstr;
                gid_t user_gid, group_gid;
-               
+
                gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
                if (!gidstr) {
                        DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's gid!\n"));
@@ -5583,7 +5873,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
                }
 
                user_gid = strtoul(gidstr, NULL, 10);
-       
+
                if (!sid_to_gid(&group_sid, &group_gid)) {
                        DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n"));
                        return NT_STATUS_UNSUCCESSFUL;
@@ -5658,21 +5948,21 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
                }
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        return NT_STATUS_OK;
 }
 
 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);
 }
@@ -5684,7 +5974,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;
@@ -5699,13 +5989,14 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
                DEBUG(0,("ldapsam_set_primary_group: failed to retrieve gid from user's group SID!\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
-       gidstr = talloc_asprintf(mem_ctx, "%d", gid);
+       gidstr = talloc_asprintf(mem_ctx, "%u", (unsigned int)gid);
        if (!gidstr) {
                DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
                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;
        }
@@ -5718,7 +6009,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;
@@ -5798,7 +6089,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))",
@@ -5848,7 +6139,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 =
@@ -5892,18 +6183,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;
@@ -5912,7 +6202,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;
@@ -5940,12 +6230,10 @@ static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaSID",
                         sid_string_tos(sid));
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaPwdLastSet",
-                        talloc_asprintf(talloc_tos(), "%li", time(NULL)));
+                        talloc_asprintf(talloc_tos(), "%li", (long int)time(NULL)));
        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());
@@ -5956,6 +6244,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;
@@ -6010,7 +6300,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;
@@ -6043,7 +6333,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;
        }
@@ -6055,7 +6345,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;
@@ -6157,7 +6447,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;
@@ -6167,7 +6457,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;
        }
@@ -6227,21 +6517,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;
@@ -6263,6 +6552,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;
@@ -6289,7 +6580,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                          "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"));
+                            "and will risk BDCs having inconsistent SIDs\n"));
                sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
                return NT_STATUS_OK;
        }
@@ -6306,14 +6597,14 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+       dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
        if (!dn) {
                ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
        ldap_state->domain_dn = smb_xstrdup(dn);
-       ldap_memfree(dn);
+       TALLOC_FREE(dn);
 
        domain_sid_string = smbldap_talloc_single_attribute(
                    ldap_state->smbldap_state->ldap_struct,
@@ -6333,7 +6624,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",
@@ -6358,7 +6649,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"
@@ -6386,5 +6677,7 @@ NTSTATUS pdb_ldap_init(void)
        /* Let pdb_nds register backends */
        pdb_nds_init();
 
+       pdb_ipa_init();
+
        return NT_STATUS_OK;
 }