s3:pdb_ldap: don't search for the users primary group, if we already know it
[ira/wip.git] / source3 / passdb / pdb_ldap.c
index bb983a6086ffdfa5b7b2ba60e8bc2b2323dbdcf9..acebd978d0ce3843b3434b6cdbca28ae191676a1 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:
@@ -44,6 +44,7 @@
 */
 
 #include "includes.h"
+#include "../libcli/auth/libcli_auth.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
@@ -97,10 +98,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 +118,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 +140,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 +148,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 +162,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 +175,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;
@@ -335,7 +336,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,6 +350,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) {
+               TALLOC_FREE(escape_user);
                return LDAP_NO_MEMORY;
        }
        /*
@@ -358,10 +360,10 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
 
        filter = talloc_all_string_sub(talloc_tos(),
                                filter, "%u", escape_user);
+       TALLOC_FREE(escape_user);
        if (!filter) {
                return LDAP_NO_MEMORY;
        }
-       SAFE_FREE(escape_user);
 
        ret = smbldap_search_suffix(ldap_state->smbldap_state,
                        filter, attr, result);
@@ -407,7 +409,7 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
        filter = talloc_asprintf(talloc_tos(), "(&(%s=%s)%s)",
                get_userattr_key2string(ldap_state->schema_ver,
                        LDAP_ATTR_USER_SID),
-               sid_to_string(sid_string, sid),
+               sid_to_fstring(sid_string, sid),
                get_objclass_filter(ldap_state->schema_ver));
        if (!filter) {
                return LDAP_NO_MEMORY;
@@ -446,7 +448,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)) {
@@ -558,7 +560,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))) {
@@ -607,7 +609,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                }
        }
 
-       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),
@@ -839,27 +841,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));
@@ -900,7 +902,7 @@ 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;
@@ -913,9 +915,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;
                }
@@ -945,7 +947,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                                }
                        }
                        if (hex_failed) {
-                               DEBUG(0,("init_sam_from_ldap: Failed to get password history for user %s\n",
+                               DEBUG(2,("init_sam_from_ldap: Failed to get password history for user %s\n",
                                        username));
                                memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
                        }
@@ -1027,6 +1029,17 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
        }
 
        if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+               struct passwd unix_pw;
+               bool have_uid = false;
+               bool have_gid = false;
+               DOM_SID mapped_gsid;
+               const 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,
@@ -1034,8 +1047,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 && sid_equal(primary_gsid, &mapped_gsid)) {
+                       store_gid_sid_cache(primary_gsid,
+                                           sampass->unix_pw->pw_gid);
+                       idmap_cache_set_sid2uid(primary_gsid,
+                                               sampass->unix_pw->pw_gid);
                }
        }
 
@@ -1152,7 +1225,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        case SCHEMAVER_SAMBASAMACCOUNT:
                                smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
                                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
-                                       sid_to_string(sid_string, user_sid));
+                                       sid_to_fstring(sid_string, user_sid));
                                break;
 
                        default:
@@ -1190,7 +1263,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        case SCHEMAVER_SAMBASAMACCOUNT:
                                smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
                                        get_userattr_key2string(ldap_state->schema_ver, 
-                                       LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
+                                       LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_fstring(sid_string, group_sid));
                                break;
 
                        default:
@@ -1248,7 +1321,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))
@@ -1256,7 +1329,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))
@@ -1264,7 +1337,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))
@@ -1272,7 +1345,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))
@@ -1280,7 +1353,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,7 +1398,7 @@ 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);
+                       pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
 
                        pwstr = SMB_MALLOC_ARRAY(char, 1024);
                        if (!pwstr) {
@@ -1360,7 +1433,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,
@@ -1402,7 +1475,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                uint16 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);
+               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));
@@ -1422,7 +1495,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(
@@ -1453,79 +1526,6 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
        return True;
 }
 
-/**********************************************************************
- Connect to LDAP server for password enumeration.
-*********************************************************************/
-
-static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, bool update, uint32 acb_mask)
-{
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
-       int rc;
-       char *filter = NULL;
-       const char *suffix;
-       const char **attr_list;
-       bool machine_mask = False, user_mask = False;
-       NTSTATUS status = NT_STATUS_OK;
-       TALLOC_CTX *ctx = talloc_init("ldapsam_setsampwent");
-
-       if (!ctx) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       filter = talloc_asprintf(ctx, "(&%s%s)", "(uid=%u)",
-               get_objclass_filter(ldap_state->schema_ver));
-       if (!filter) {
-               status = NT_STATUS_NO_MEMORY;
-               goto out;
-       }
-
-       filter = talloc_all_string_sub(ctx, filter, "%u", "*");
-       if (!filter) {
-               status = NT_STATUS_NO_MEMORY;
-               goto out;
-       }
-
-       machine_mask    = ((acb_mask != 0) && (acb_mask & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)));
-       user_mask       = ((acb_mask != 0) && (acb_mask & ACB_NORMAL));
-
-       if (machine_mask) {
-               suffix = lp_ldap_machine_suffix();
-       } else if (user_mask) {
-               suffix = lp_ldap_user_suffix();
-       } else {
-               suffix = lp_ldap_suffix();
-       }
-
-       DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n", 
-               acb_mask, suffix));
-
-       attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
-       rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, 
-                           attr_list, 0, &ldap_state->result);
-       TALLOC_FREE( attr_list );
-
-       if (rc != LDAP_SUCCESS) {
-               DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
-               DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", suffix, filter));
-               ldap_msgfree(ldap_state->result);
-               ldap_state->result = NULL;
-               status = NT_STATUS_UNSUCCESSFUL;
-               goto out;
-       }
-
-       DEBUG(2, ("ldapsam_setsampwent: %d entries in the base %s\n",
-               ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
-               ldap_state->result), suffix));
-
-       ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
-                                ldap_state->result);
-       ldap_state->index = 0;
-
-  out:
-
-       TALLOC_FREE(ctx);
-       return status;
-}
-
 /**********************************************************************
  End enumeration of the LDAP password list.
 *********************************************************************/
@@ -1539,32 +1539,6 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods)
        }
 }
 
-/**********************************************************************
-Get the next entry in the LDAP password database.
-*********************************************************************/
-
-static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
-                                   struct samu *user)
-{
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state =
-               (struct ldapsam_privates *)my_methods->private_data;
-       bool bret = False;
-
-       while (!bret) {
-               if (!ldap_state->entry)
-                       return ret;
-               
-               ldap_state->index++;
-               bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
-               
-               ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
-                                                   ldap_state->entry); 
-       }
-
-       return NT_STATUS_OK;
-}
-
 static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
                        const char *new_attr)
 {
@@ -1585,6 +1559,16 @@ static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
        (*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.
 *********************************************************************/
@@ -1598,21 +1582,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);
@@ -1660,7 +1644,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);
@@ -1669,12 +1653,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 );
@@ -1705,7 +1689,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));
@@ -1749,11 +1733,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 */
@@ -1781,12 +1765,12 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                                         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) &&
@@ -1797,6 +1781,8 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                struct berval *retdata = NULL;
                char *utf8_password;
                char *utf8_dn;
+               size_t converted_size;
+               int ret;
 
                if (!ldap_state->is_nds_ldap) {
 
@@ -1808,37 +1794,63 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                        }
                }
 
-               if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
+               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) == (size_t)-1) {
-                       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;
                }
 
-               ber_printf (ber, "{");
-               ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
-               ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
-               ber_printf (ber, "n}");
+               if ((ber_printf (ber, "{") < 0) ||
+                   (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) {
@@ -1867,6 +1879,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                                pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
                        SAFE_FREE(ld_error);
                        ber_bvfree(bv);
+#if defined(LDAP_CONSTRAINT_VIOLATION)
+                       if (rc == LDAP_CONSTRAINT_VIOLATION)
+                               return NT_STATUS_PASSWORD_RESTRICTION;
+#endif
                        return NT_STATUS_UNSUCCESSFUL;
                } else {
                        DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
@@ -1929,7 +1945,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 ?
@@ -1992,7 +2008,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;
        }
@@ -2002,22 +2018,27 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
        if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
                                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;
        }
-       
-       if (mods == NULL) {
+
+       if ((lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_ONLY)
+           && (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);
-       ldap_mods_free(mods,True);
-       SAFE_FREE(dn);
+
+       if (mods != NULL) {
+               ldap_mods_free(mods,True);
+       }
+
+       TALLOC_FREE(dn);
 
        /*
         * We need to set the backend private data to NULL here. For example
@@ -2046,6 +2067,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 group_rid,
+                                    uint32 member_rid);
+
+static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
+                                              TALLOC_CTX *mem_ctx,
+                                              struct samu *user,
+                                              DOM_SID **pp_sids,
+                                              gid_t **pp_gids,
+                                              size_t *p_num_groups);
+
 static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
                                           struct samu *old_acct,
                                           const char *newname)
@@ -2068,7 +2101,7 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
 
        /* rename the posix user */
        rename_script = SMB_STRDUP(lp_renameuser_script());
-       if (rename_script) {
+       if (rename_script == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -2093,7 +2126,7 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
                                        newname_lower,
                                        true,
                                        true);
-       if (rename_script) {
+       if (!rename_script) {
                return NT_STATUS_NO_MEMORY;
        }
        rename_script = realloc_string_sub2(rename_script,
@@ -2198,18 +2231,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);
@@ -2226,17 +2259,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;
@@ -2279,17 +2305,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;
@@ -2369,7 +2389,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);
        }
@@ -2389,7 +2408,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);
 
@@ -2511,6 +2530,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);
@@ -2577,11 +2597,12 @@ static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
 {
        char *filter = NULL;
        NTSTATUS status;
+       fstring tmp;
 
        if (asprintf(&filter, "(&(objectClass=%s)(%s=%s))",
                LDAP_OBJ_GROUPMAP,
                get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
-               sid_string_static(&sid)) < 0) {
+               sid_to_fstring(tmp, &sid)) < 0) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -2618,7 +2639,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) {
@@ -2630,11 +2651,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;
@@ -2708,7 +2729,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);
 
@@ -2744,7 +2765,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) {
@@ -2755,20 +2776,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, "))");
@@ -2777,7 +2797,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                        goto done;
                }
 
-               rc = smbldap_search(conn, lp_ldap_user_suffix(),
+               rc = smbldap_search(conn, lp_ldap_suffix(),
                                    LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
                                    &result);
 
@@ -2801,8 +2821,8 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                                                                 entry, "sambaSID",
                                                                 mem_ctx);
                        if (!sidstr) {
-                               DEBUG(0, ("Severe DB error, sambaSamAccount can't miss "
-                                         "the sambaSID attribute\n"));
+                               DEBUG(0, ("Severe DB error, %s can't miss the sambaSID"
+                                         "attribute\n", LDAP_OBJ_SAMBASAMACCOUNT));
                                ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
                                goto done;
                        }
@@ -2833,7 +2853,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                                 LDAP_OBJ_SAMBASAMACCOUNT,
                                 gidstr);
 
-       rc = smbldap_search(conn, lp_ldap_user_suffix(),
+       rc = smbldap_search(conn, lp_ldap_suffix(),
                            LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
                            &result);
 
@@ -2852,8 +2872,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                                                    entry,
                                                    get_global_sam_sid(),
                                                    &rid)) {
-                       DEBUG(0, ("Severe DB error, sambaSamAccount can't miss "
-                                 "the sambaSID attribute\n"));
+                       DEBUG(0, ("Severe DB error, %s can't miss the samba SID"                                                                "attribute\n", LDAP_OBJ_SAMBASAMACCOUNT));
                        ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
                        goto done;
                }
@@ -2866,7 +2885,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
        }
 
        ret = NT_STATUS_OK;
-       
+
  done:
 
        if (values)
@@ -2903,61 +2922,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_user_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)
@@ -2980,8 +3003,9 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
        /* This sid will be replaced later */
 
-       if (!add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids)) {
-               ret = NT_STATUS_NO_MEMORY;
+       ret = add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids,
+                                     &num_sids);
+       if (!NT_STATUS_IS_OK(ret)) {
                goto done;
        }
 
@@ -3020,9 +3044,9 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                                ret = NT_STATUS_NO_MEMORY;
                                goto done;
                        }
-                       if (!add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
-                                               &num_sids)) {
-                               ret = NT_STATUS_NO_MEMORY;
+                       ret = add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
+                                                     &num_sids);
+                       if (!NT_STATUS_IS_OK(ret)) {
                                goto done;
                        }
                }
@@ -3040,7 +3064,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
  done:
 
-       SAFE_FREE(escape_name);
+       TALLOC_FREE(escape_name);
        return ret;
 }
 
@@ -3058,8 +3082,8 @@ static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
        int rc;
 
        filter = talloc_asprintf(mem_ctx,
-                                "(&(objectClass=posixGroup)(gidNumber=%u))",
-                                map->gid);
+                                "(&(objectClass=%s)(gidNumber=%u))",
+                                LDAP_OBJ_POSIXGROUP, (unsigned int)map->gid);
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -3082,9 +3106,9 @@ static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
 
        mods = NULL;
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
-                       "sambaGroupMapping");
+                       LDAP_OBJ_GROUPMAP);
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
-                        sid_string_static(&map->sid));
+                        sid_string_talloc(mem_ctx, &map->sid));
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
                         talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
@@ -3182,8 +3206,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;
        }
@@ -3202,10 +3226,9 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
        mods = NULL;
 
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
-                        "sambaSidEntry");
+                        LDAP_OBJ_SID_ENTRY);
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
-                        "sambaGroupMapping");
-
+                        LDAP_OBJ_GROUPMAP);
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
                         sid_string_talloc(mem_ctx, &map->sid));
        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
@@ -3215,7 +3238,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);
@@ -3261,7 +3284,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;
@@ -3359,8 +3382,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",
@@ -3375,6 +3399,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",
@@ -3413,7 +3438,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);
@@ -3422,7 +3447,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);
@@ -3465,11 +3490,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);     
@@ -3545,6 +3570,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
        LDAPMod **mods = NULL;
        int rc;
        enum lsa_SidType type = SID_NAME_USE_NONE;
+       fstring tmp;
 
        char *filter = NULL;
 
@@ -3564,7 +3590,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
 
        if (asprintf(&filter,
                     "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
-                    LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+                    LDAP_OBJ_GROUPMAP, sid_to_fstring(tmp, alias),
                     type) < 0) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -3603,7 +3629,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;
@@ -3612,13 +3638,13 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
        smbldap_set_mod(&mods, modop,
                        get_attr_key2string(groupmap_attr_list,
                                            LDAP_ATTR_SID_LIST),
-                       sid_string_static(member));
+                       sid_to_fstring(tmp, member));
 
        rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
 
        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;
@@ -3652,6 +3678,7 @@ static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
 
 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
                                      const DOM_SID *alias,
+                                     TALLOC_CTX *mem_ctx,
                                      DOM_SID **pp_members,
                                      size_t *p_num_members)
 {
@@ -3665,6 +3692,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
        char *filter = NULL;
        size_t num_members = 0;
        enum lsa_SidType type = SID_NAME_USE_NONE;
+       fstring tmp;
 
        *pp_members = NULL;
        *p_num_members = 0;
@@ -3685,7 +3713,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
 
        if (asprintf(&filter,
                     "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
-                    LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+                    LDAP_OBJ_GROUPMAP, sid_to_fstring(tmp, alias),
                     type) < 0) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -3738,14 +3766,17 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
 
        for (i=0; i<count; i++) {
                DOM_SID member;
+               NTSTATUS status;
 
                if (!string_to_sid(&member, values[i]))
                        continue;
 
-               if (!add_sid_to_array(NULL, &member, pp_members, &num_members)) {
+               status = add_sid_to_array(mem_ctx, &member, pp_members,
+                                         &num_members);
+               if (!NT_STATUS_IS_OK(status)) {
                        ldap_value_free(values);
                        ldap_msgfree(result);
-                       return NT_STATUS_NO_MEMORY;
+                       return status;
                }
        }
 
@@ -3776,8 +3807,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;
        }
 
@@ -3791,6 +3828,10 @@ 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))(|",
                                 LDAP_OBJ_GROUPMAP, type);
@@ -3807,11 +3848,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;
 
@@ -3835,19 +3885,29 @@ 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,
+                                                  enum pdb_policy_type type,
                                                   uint32 value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
@@ -3865,7 +3925,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"));
@@ -3885,7 +3945,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;
@@ -3895,14 +3955,15 @@ 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,
+                                                    enum pdb_policy_type type,
                                                     uint32 *value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
@@ -3911,6 +3972,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 =
@@ -3924,18 +3986,22 @@ 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(NULL, "(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);
 
        if (rc != LDAP_SUCCESS) {
@@ -3958,7 +4024,7 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
        }
 
        *value = (uint32)atol(vals[0]);
-       
+
        ntstatus = NT_STATUS_OK;
 
 out:
@@ -3973,7 +4039,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
@@ -3981,17 +4047,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;
@@ -4002,27 +4069,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;
@@ -4061,6 +4128,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;
 
@@ -4072,8 +4144,9 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
        for (i=0; i<num_rids; i++) {
                DOM_SID sid;
                sid_compose(&sid, domain_sid, rids[i]);
-               allsids = talloc_asprintf_append_buffer(allsids, "(sambaSid=%s)",
-                                                sid_string_static(&sid));
+               allsids = talloc_asprintf_append_buffer(
+                       allsids, "(sambaSid=%s)",
+                       sid_string_talloc(mem_ctx, &sid));
                if (allsids == NULL) {
                        goto done;
                }
@@ -4162,7 +4235,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);
@@ -4257,18 +4330,19 @@ static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
        char *escaped = NULL;
        char *result = NULL;
 
-       asprintf(&filter, "(&%s(objectclass=sambaSamAccount))",
-                "(uid=%u)");
-       if (filter == NULL) goto done;
+       if (asprintf(&filter, "(&%s(objectclass=%s))",
+                         "(uid=%u)", LDAP_OBJ_SAMBASAMACCOUNT) < 0) {
+               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;
 }
@@ -4293,6 +4367,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;
                }
        }
@@ -4370,6 +4445,7 @@ static bool ldapsam_search_firstpage(struct pdb_search *search)
        if (state->current_entry == NULL) {
                ldap_msgfree(state->entries);
                state->entries = NULL;
+               return false;
        }
 
        return True;
@@ -4400,6 +4476,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;
@@ -4420,7 +4497,8 @@ 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,
+       result = state->ldap2displayentry(state, search,
+                                         state->connection->ldap_struct,
                                          state->current_entry, entry);
 
        if (!result) {
@@ -4479,6 +4557,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
                                  struct samr_displayentry *result)
 {
        char **vals;
+       size_t converted_size;
        DOM_SID sid;
        uint32 acct_flags;
 
@@ -4504,27 +4583,40 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
                DEBUG(5, ("\"uid\" not found\n"));
                return False;
        }
-       pull_utf8_talloc(mem_ctx,
-                        CONST_DISCARD(char **, &result->account_name),
-                        vals[0]);
+       if (!pull_utf8_talloc(mem_ctx,
+                             CONST_DISCARD(char **, &result->account_name),
+                             vals[0], &converted_size))
+       {
+               DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
+                        strerror(errno)));
+       }
+
        ldap_value_free(vals);
 
        vals = ldap_get_values(ld, entry, "displayName");
        if ((vals == NULL) || (vals[0] == NULL))
                DEBUG(8, ("\"displayName\" not found\n"));
-       else
-               pull_utf8_talloc(mem_ctx,
-                                CONST_DISCARD(char **, &result->fullname),
-                                vals[0]);
+       else if (!pull_utf8_talloc(mem_ctx,
+                                  CONST_DISCARD(char **, &result->fullname),
+                                  vals[0], &converted_size))
+       {
+               DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
+                        strerror(errno)));
+       }
+
        ldap_value_free(vals);
 
        vals = ldap_get_values(ld, entry, "description");
        if ((vals == NULL) || (vals[0] == NULL))
                DEBUG(8, ("\"description\" not found\n"));
-       else
-               pull_utf8_talloc(mem_ctx,
-                                CONST_DISCARD(char **, &result->description),
-                                vals[0]);
+       else if (!pull_utf8_talloc(mem_ctx,
+                                  CONST_DISCARD(char **, &result->description),
+                                  vals[0], &converted_size))
+       {
+               DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
+                        strerror(errno)));
+       }
+
        ldap_value_free(vals);
 
        if ((result->account_name == NULL) ||
@@ -4533,7 +4625,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"));
@@ -4565,7 +4657,7 @@ static bool ldapsam_search_users(struct pdb_methods *methods,
                (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;
@@ -4582,10 +4674,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;
@@ -4611,6 +4703,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                                   struct samr_displayentry *result)
 {
        char **vals;
+       size_t converted_size;
        DOM_SID sid;
        uint16 group_type;
 
@@ -4650,14 +4743,22 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                        DEBUG(5, ("\"cn\" not found\n"));
                        return False;
                }
-               pull_utf8_talloc(mem_ctx,
-                                CONST_DISCARD(char **, &result->account_name),
-                                vals[0]);
+               if (!pull_utf8_talloc(mem_ctx,
+                                     CONST_DISCARD(char **,
+                                                   &result->account_name),
+                                     vals[0], &converted_size))
+               {
+                       DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc "
+                                 "failed: %s", strerror(errno)));
+               }
        }
-       else {
-               pull_utf8_talloc(mem_ctx,
-                                CONST_DISCARD(char **, &result->account_name),
-                                vals[0]);
+       else if (!pull_utf8_talloc(mem_ctx,
+                                  CONST_DISCARD(char **,
+                                                &result->account_name),
+                                  vals[0], &converted_size))
+       {
+               DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
+                         strerror(errno)));
        }
 
        ldap_value_free(vals);
@@ -4665,10 +4766,13 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
        vals = ldap_get_values(ld, entry, "description");
        if ((vals == NULL) || (vals[0] == NULL))
                DEBUG(8, ("\"description\" not found\n"));
-       else
-               pull_utf8_talloc(mem_ctx,
-                                CONST_DISCARD(char **, &result->description),
-                                vals[0]);
+       else if (!pull_utf8_talloc(mem_ctx,
+                                  CONST_DISCARD(char **, &result->description),
+                                  vals[0], &converted_size))
+       {
+               DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
+                         strerror(errno)));
+       }
        ldap_value_free(vals);
 
        if ((result->account_name == NULL) ||
@@ -4677,7 +4781,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"));
@@ -4706,12 +4810,14 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
                                return False;
                        }
                        break;
-       
+
                default:
                        DEBUG(0,("unkown group type: %d\n", group_type));
                        return False;
        }
-       
+
+       result->acct_flags = 0;
+
        return True;
 }
 
@@ -4723,8 +4829,9 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods,
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
        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;
@@ -4732,14 +4839,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=sambaGroupMapping)"
-                                       "(sambaGroupType=%d)(sambaSID=%s*))", 
-                                       type, sid_string_static(sid));
-       state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
+       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, "cn", "sambaSid",
                                    "displayName", "description",
                                    "sambaGroupType", NULL);
        state->attrsonly = 0;
@@ -4773,9 +4880,9 @@ static bool ldapsam_search_aliases(struct pdb_methods *methods,
        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,
@@ -4969,6 +5076,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;
        }
@@ -4985,6 +5094,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:
@@ -4992,8 +5103,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,
+                              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,
+                              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;
+       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
  */
@@ -5031,7 +5285,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
        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 ||
@@ -5039,15 +5293,15 @@ 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) {
                DEBUG(0,("ldapsam_create_user: ldap search failed!\n"));
-               return NT_STATUS_UNSUCCESSFUL;
+               return NT_STATUS_ACCESS_DENIED;
        }
        talloc_autofree_ldapmsg(tmp_ctx, result);
 
@@ -5057,7 +5311,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.
@@ -5086,7 +5340,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"));
@@ -5170,8 +5424,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) {
@@ -5232,7 +5486,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)"
@@ -5275,6 +5529,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;
+               size_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;
@@ -5314,11 +5602,11 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        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) {
@@ -5333,7 +5621,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.
@@ -5357,7 +5645,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);
@@ -5373,14 +5661,14 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                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) {
@@ -5570,7 +5858,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);
 
@@ -5617,7 +5905,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"));
@@ -5625,7 +5913,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;
@@ -5700,7 +5988,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
                }
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        return NT_STATUS_OK;
 }
 
@@ -5738,16 +6026,17 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
        DEBUG(0,("ldapsam_set_primary_group: Attempt to set primary group for user [%s]\n", pdb_get_username(sampass)));
 
        if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
-               DEBUG(0,("ldapsam_set_primary_group: failed to retieve gid from user's group SID!\n"));
+               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;
        }
@@ -5760,7 +6049,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;
@@ -5830,6 +6119,7 @@ static char *trusteddom_dn(struct ldapsam_privates *ldap_state,
 }
 
 static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
+                                 TALLOC_CTX *mem_ctx,
                                  const char *domain, LDAPMessage **entry)
 {
        int rc;
@@ -5852,6 +6142,10 @@ static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
        rc = smbldap_search(ldap_state->smbldap_state, trusted_dn, scope,
                            filter, attrs, attrsonly, &result);
 
+       if (result != NULL) {
+               talloc_autofree_ldapmsg(mem_ctx, result);
+       }
+
        if (rc == LDAP_NO_SUCH_OBJECT) {
                *entry = NULL;
                return True;
@@ -5865,15 +6159,15 @@ static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
 
        if (num_result > 1) {
                DEBUG(1, ("ldapsam_get_trusteddom_pw: more than one "
-                         "sambaTrustedDomainPassword object for domain '%s'"
-                         "?!\n", domain));
+                         "%s object for domain '%s'?!\n",
+                         LDAP_OBJ_TRUSTDOM_PASSWORD, domain));
                return False;
        }
 
        if (num_result == 0) {
                DEBUG(1, ("ldapsam_get_trusteddom_pw: no "
-                         "sambaTrustedDomainPassword object for domain %s.\n",
-                         domain));
+                         "%s object for domain %s.\n",
+                         LDAP_OBJ_TRUSTDOM_PASSWORD, domain));
                *entry = NULL;
        } else {
                *entry = ldap_first_entry(priv2ld(ldap_state), result);
@@ -5894,7 +6188,7 @@ static bool ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
 
        DEBUG(10, ("ldapsam_get_trusteddom_pw called for domain %s\n", domain));
 
-       if (!get_trusteddom_pw_int(ldap_state, domain, &entry) ||
+       if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry) ||
            (entry == NULL))
        {
                return False;
@@ -5929,18 +6223,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;
@@ -5965,21 +6258,22 @@ static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
         * get the current entry (if there is one) in order to put the
         * current password into the previous password attribute
         */
-       if (!get_trusteddom_pw_int(ldap_state, domain, &entry)) {
+       if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry)) {
                return False;
        }
 
        mods = NULL;
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
-                        "sambaTrustedDomainPassword");
+                        LDAP_OBJ_TRUSTDOM_PASSWORD);
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaDomainName",
                         domain);
        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);
+
        if (entry != NULL) {
                prev_pwd = smbldap_talloc_single_attribute(priv2ld(ldap_state),
                                entry, "sambaClearTextPassword", talloc_tos());
@@ -5990,6 +6284,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;
@@ -6017,7 +6313,7 @@ static bool ldapsam_del_trusteddom_pw(struct pdb_methods *methods,
        LDAPMessage *entry = NULL;
        const char *trusted_dn;
 
-       if (!get_trusteddom_pw_int(ldap_state, domain, &entry)) {
+       if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry)) {
                return False;
        }
 
@@ -6068,6 +6364,10 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
                            attrsonly,
                            &result);
 
+       if (result != NULL) {
+               talloc_autofree_ldapmsg(mem_ctx, result);
+       }
+
        if (rc != LDAP_SUCCESS) {
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -6167,9 +6467,6 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
 
        (*pdb_method)->name = "ldapsam";
 
-       (*pdb_method)->setsampwent = ldapsam_setsampwent;
-       (*pdb_method)->endsampwent = ldapsam_endsampwent;
-       (*pdb_method)->getsampwent = ldapsam_getsampwent;
        (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
        (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
        (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
@@ -6190,7 +6487,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;
@@ -6272,9 +6569,8 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *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;
@@ -6296,6 +6592,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;
@@ -6339,21 +6637,21 @@ 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,
                    entry,
                    get_userattr_key2string(ldap_state->schema_ver,
                                            LDAP_ATTR_USER_SID),
-                   NULL);
+                   talloc_tos());
 
        if (domain_sid_string) {
                bool found_sid;
@@ -6389,7 +6687,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                    entry,
                    get_attr_key2string( dominfo_attr_list,
                                         LDAP_ATTR_ALGORITHMIC_RID_BASE ),
-                   NULL);
+                   talloc_tos());
        if (alg_rid_base_string) {
                alg_rid_base = (uint32)atol(alg_rid_base_string);
                if (alg_rid_base != algorithmic_rid_base()) {