[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / passdb / pdb_ldap.c
index 2b1893e4c0cc4f72532cac12841b208b3fdc3e76..a945867967bc0c4b4a7a245c2bae14940226d653 100644 (file)
@@ -10,7 +10,7 @@
     
    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
     
    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 2 of the License, or
+   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,
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -19,8 +19,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
 */
 
    
 */
 
@@ -455,7 +454,11 @@ static time_t ldapsam_get_entry_timestamp( struct ldapsam_privates *ldap_state,
                        temp))
                return (time_t) 0;
 
                        temp))
                return (time_t) 0;
 
-       strptime(temp, "%Y%m%d%H%M%SZ", &tm);
+       if ( !strptime(temp, "%Y%m%d%H%M%SZ", &tm)) {
+               DEBUG(2,("ldapsam_get_entry_timestamp: strptime failed on: %s\n",
+                       (char*)temp));
+               return (time_t) 0;
+       }
        tzset();
        return timegm(&tm);
 }
        tzset();
        return timegm(&tm);
 }
@@ -650,12 +653,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) 
        {
                pdb_set_homedir( sampass, 
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) 
        {
                pdb_set_homedir( sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_home()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, homedir );
                if (expand_explicit) {
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, homedir );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_homedir(sampass, tmpstring, PDB_SET);
                                            sizeof(tmpstring) );
                }
                pdb_set_homedir(sampass, tmpstring, PDB_SET);
@@ -665,12 +669,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) 
        {
                pdb_set_logon_script( sampass, 
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) 
        {
                pdb_set_logon_script( sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_script()), 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()), 
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, logon_script );
                if (expand_explicit) {
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, logon_script );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_logon_script(sampass, tmpstring, PDB_SET);
                                            sizeof(tmpstring) );
                }
                pdb_set_logon_script(sampass, tmpstring, PDB_SET);
@@ -680,12 +685,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) 
        {
                pdb_set_profile_path( sampass, 
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) 
        {
                pdb_set_profile_path( sampass, 
-                       talloc_sub_basic( sampass, username, lp_logon_path()),
+                       talloc_sub_basic( sampass, username, domain,
+                                         lp_logon_path()),
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, profile_path );
                if (expand_explicit) {
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, profile_path );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_profile_path(sampass, tmpstring, PDB_SET);
                                            sizeof(tmpstring) );
                }
                pdb_set_profile_path(sampass, tmpstring, PDB_SET);
@@ -787,7 +793,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
                pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
 
 
                pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
 
-               if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
+               if ((pwhist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
                        DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
                        return False;
                }
                        DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
                        return False;
                }
@@ -967,15 +973,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
        /* only update the RID if we actually need to */
        if (need_update(sampass, PDB_USERSID)) {
                fstring sid_string;
        /* only update the RID if we actually need to */
        if (need_update(sampass, PDB_USERSID)) {
                fstring sid_string;
-               fstring dom_sid_string;
                const DOM_SID *user_sid = pdb_get_user_sid(sampass);
                
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
                                if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
                                        DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", 
                const DOM_SID *user_sid = pdb_get_user_sid(sampass);
                
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
                                if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
                                        DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", 
-                                               sid_to_string(sid_string, user_sid), 
-                                               sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+                                                 sid_string_static(user_sid), 
+                                                 sid_string_static(&ldap_state->domain_sid)));
                                        return False;
                                }
                                slprintf(temp, sizeof(temp) - 1, "%i", rid);
                                        return False;
                                }
                                slprintf(temp, sizeof(temp) - 1, "%i", rid);
@@ -1001,15 +1006,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
        if (need_update(sampass, PDB_GROUPSID)) {
                fstring sid_string;
 
        if (need_update(sampass, PDB_GROUPSID)) {
                fstring sid_string;
-               fstring dom_sid_string;
                const DOM_SID *group_sid = pdb_get_group_sid(sampass);
                
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
                                if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
                                        DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
                const DOM_SID *group_sid = pdb_get_group_sid(sampass);
                
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
                                if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
                                        DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
-                                               sid_to_string(sid_string, group_sid),
-                                               sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+                                                 sid_string_static(group_sid),
+                                                 sid_string_static(&ldap_state->domain_sid)));
                                        return False;
                                }
 
                                        return False;
                                }
 
@@ -1095,7 +1099,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
 
                smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
 
-       slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
+       slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time_noncalc(sampass));
        if (need_update(sampass, PDB_CANCHANGETIME))
                smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
        if (need_update(sampass, PDB_CANCHANGETIME))
                smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
@@ -1592,19 +1596,21 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                }
 
                if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
                }
 
                if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
+                       SAFE_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);
                        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);
                        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);
                        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}");
+               ber_printf (ber, "n}");
 
                if ((rc = ber_flatten (ber, &bv))<0) {
                        DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
 
                if ((rc = ber_flatten (ber, &bv))<0) {
                        DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
@@ -1747,7 +1753,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
        LDAPMod **mods = NULL;
        const char **attr_list;
 
        LDAPMod **mods = NULL;
        const char **attr_list;
 
-       result = pdb_get_backend_private_data(newpwd, my_methods);
+       result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods);
        if (!result) {
                attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
                if (pdb_get_username(newpwd) == NULL) {
        if (!result) {
                attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
                if (pdb_get_username(newpwd) == NULL) {
@@ -1830,6 +1836,7 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
        const char *oldname;
        int rc;
        pstring rename_script;
        const char *oldname;
        int rc;
        pstring rename_script;
+       fstring oldname_lower, newname_lower;
 
        if (!old_acct) {
                DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
 
        if (!old_acct) {
                DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
@@ -1851,16 +1858,27 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
        DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n", 
                   oldname, newname));
 
        DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n", 
                   oldname, newname));
 
-       /* we have to allow the account name to end with a '$' */
-       string_sub2(rename_script, "%unew", newname, sizeof(pstring), 
+       /* We have to allow the account name to end with a '$'.
+          Also, follow the semantics in _samr_create_user() and lower case the
+          posix name but preserve the case in passdb */
+
+       fstrcpy( oldname_lower, oldname );
+       strlower_m( oldname_lower );
+       fstrcpy( newname_lower, newname );
+       strlower_m( newname_lower );
+       string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring), 
                    True, False, True);
                    True, False, True);
-       string_sub2(rename_script, "%uold", oldname, sizeof(pstring), 
+       string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring), 
                    True, False, True);
        rc = smbrun(rename_script, NULL);
 
        DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n", 
                          rename_script, rc));
 
                    True, False, True);
        rc = smbrun(rename_script, NULL);
 
        DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n", 
                          rename_script, rc));
 
+       if (rc == 0) {
+               smb_nscd_flush_user_cache();
+       }
+
        if (rc)
                return NT_STATUS_UNSUCCESSFUL;
 
        if (rc)
                return NT_STATUS_UNSUCCESSFUL;
 
@@ -2034,14 +2052,25 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
        TALLOC_FREE( attr_list );
 
        if (num_result == 0) {
        TALLOC_FREE( attr_list );
 
        if (num_result == 0) {
+               char *escape_username;
                /* Check if we need to add an entry */
                DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
                ldap_op = LDAP_MOD_ADD;
                /* Check if we need to add an entry */
                DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
                ldap_op = LDAP_MOD_ADD;
+
+               escape_username = escape_rdn_val_string_alloc(username);
+               if (!escape_username) {
+                       DEBUG(0, ("Out of memory!\n"));
+                       ldap_msgfree(result);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                if (username[strlen(username)-1] == '$') {
                if (username[strlen(username)-1] == '$') {
-                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
+                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_machine_suffix ());
                } else {
                } else {
-                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
+                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_user_suffix ());
                }
                }
+
+               SAFE_FREE(escape_username);
        }
 
        if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
        }
 
        if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
@@ -2147,7 +2176,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
                        get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
                return False;
        }
                        get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
                return False;
        }
-       map->sid_name_use = (enum SID_NAME_USE)atol(temp);
+       map->sid_name_use = (enum lsa_SidType)atol(temp);
 
        if ((map->sid_name_use < SID_NAME_USER) ||
                        (map->sid_name_use > SID_NAME_UNKNOWN)) {
 
        if ((map->sid_name_use < SID_NAME_USER) ||
                        (map->sid_name_use > SID_NAME_UNKNOWN)) {
@@ -2393,21 +2422,32 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 
        if (values) {
 
 
        if (values) {
 
-               filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBAACCOUNT);
+               filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBASAMACCOUNT);
                if (filter == NULL) {
                        ret = NT_STATUS_NO_MEMORY;
                        goto done;
                }
 
                for (memberuid = values; *memberuid != NULL; memberuid += 1) {
                if (filter == NULL) {
                        ret = NT_STATUS_NO_MEMORY;
                        goto done;
                }
 
                for (memberuid = values; *memberuid != NULL; memberuid += 1) {
-                       filter = talloc_asprintf_append(filter, "(uid=%s)", *memberuid);
+                       char *escape_memberuid;
+
+                       escape_memberuid = escape_ldap_string_alloc(*memberuid);
+                       if (escape_memberuid == NULL) {
+                               ret = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
+                       
+                       filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid);
                        if (filter == NULL) {
                        if (filter == NULL) {
+                               SAFE_FREE(escape_memberuid);
                                ret = NT_STATUS_NO_MEMORY;
                                goto done;
                        }
                                ret = NT_STATUS_NO_MEMORY;
                                goto done;
                        }
+
+                       SAFE_FREE(escape_memberuid);
                }
 
                }
 
-               filter = talloc_asprintf_append(filter, "))");
+               filter = talloc_asprintf_append_buffer(filter, "))");
                if (filter == NULL) {
                        ret = NT_STATUS_NO_MEMORY;
                        goto done;
                if (filter == NULL) {
                        ret = NT_STATUS_NO_MEMORY;
                        goto done;
@@ -2455,8 +2495,11 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 
                        sid_peek_rid(&sid, &rid);
 
 
                        sid_peek_rid(&sid, &rid);
 
-                       add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
-                                               p_num_members);
+                       if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+                                               p_num_members)) {
+                               ret = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
                }
        }
 
                }
        }
 
@@ -2491,8 +2534,11 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                        goto done;
                }
 
                        goto done;
                }
 
-               add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
-                                       p_num_members);
+               if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+                                       p_num_members)) {
+                       ret = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
        }
 
        ret = NT_STATUS_OK;
        }
 
        ret = NT_STATUS_OK;
@@ -2574,7 +2620,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                primary_gid = strtoul(gidstr, NULL, 10);
                break;
        default:
                primary_gid = strtoul(gidstr, NULL, 10);
                break;
        default:
-               DEBUG(1, ("found more than one accoutn with the same user name ?!\n"));
+               DEBUG(1, ("found more than one account with the same user name ?!\n"));
                ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto done;
        }
                ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto done;
        }
@@ -2603,11 +2649,17 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
        /* We need to add the primary group as the first gid/sid */
 
 
        /* We need to add the primary group as the first gid/sid */
 
-       add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids);
+       if (!add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids)) {
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
        /* This sid will be replaced later */
 
 
        /* This sid will be replaced later */
 
-       add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
+       if (!add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids)) {
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
        for (entry = ldap_first_entry(conn->ldap_struct, result);
             entry != NULL;
 
        for (entry = ldap_first_entry(conn->ldap_struct, result);
             entry != NULL;
@@ -2639,10 +2691,16 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                if (gid == primary_gid) {
                        sid_copy(&(*pp_sids)[0], &sid);
                } else {
                if (gid == primary_gid) {
                        sid_copy(&(*pp_sids)[0], &sid);
                } else {
-                       add_gid_to_array_unique(mem_ctx, gid, pp_gids,
-                                               &num_gids);
-                       add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
-                                               &num_sids);
+                       if (!add_gid_to_array_unique(mem_ctx, gid, pp_gids,
+                                               &num_gids)) {
+                               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;
+                               goto done;
+                       }
                }
        }
 
                }
        }
 
@@ -3095,7 +3153,7 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
  *********************************************************************/
 
 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
  *********************************************************************/
 
 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
-                                          const DOM_SID *domsid, enum SID_NAME_USE sid_name_use,
+                                          const DOM_SID *domsid, enum lsa_SidType sid_name_use,
                                           GROUP_MAP **pp_rmap,
                                           size_t *p_num_entries,
                                           BOOL unix_only)
                                           GROUP_MAP **pp_rmap,
                                           size_t *p_num_entries,
                                           BOOL unix_only)
@@ -3157,7 +3215,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
        int count;
        LDAPMod **mods = NULL;
        int rc;
        int count;
        LDAPMod **mods = NULL;
        int rc;
-       enum SID_NAME_USE type = SID_NAME_USE_NONE;
+       enum lsa_SidType type = SID_NAME_USE_NONE;
 
        pstring filter;
 
 
        pstring filter;
 
@@ -3269,7 +3327,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
        int i;
        pstring filter;
        size_t num_members = 0;
        int i;
        pstring filter;
        size_t num_members = 0;
-       enum SID_NAME_USE type = SID_NAME_USE_NONE;
+       enum lsa_SidType type = SID_NAME_USE_NONE;
 
        *pp_members = NULL;
        *p_num_members = 0;
 
        *pp_members = NULL;
        *p_num_members = 0;
@@ -3339,7 +3397,11 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
                if (!string_to_sid(&member, values[i]))
                        continue;
 
                if (!string_to_sid(&member, values[i]))
                        continue;
 
-               add_sid_to_array(NULL, &member, pp_members, &num_members);
+               if (!add_sid_to_array(NULL, &member, pp_members, &num_members)) {
+                       ldap_value_free(values);
+                       ldap_msgfree(result);
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        *p_num_members = num_members;
        }
 
        *p_num_members = num_members;
@@ -3368,7 +3430,7 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
        int i;
        int rc;
        char *filter;
        int i;
        int rc;
        char *filter;
-       enum SID_NAME_USE type = SID_NAME_USE_NONE;
+       enum lsa_SidType type = SID_NAME_USE_NONE;
 
        if (sid_check_is_builtin(domain_sid)) {
                type = SID_NAME_ALIAS;
 
        if (sid_check_is_builtin(domain_sid)) {
                type = SID_NAME_ALIAS;
@@ -3427,8 +3489,11 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
                if (!sid_peek_check_rid(domain_sid, &sid, &rid))
                        continue;
 
                if (!sid_peek_check_rid(domain_sid, &sid, &rid))
                        continue;
 
-               add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
-                                       p_num_alias_rids);
+               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);
        }
 
        ldap_msgfree(result);
@@ -3448,8 +3513,6 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
 
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
 
-       const char *attrs[2];
-
        DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
 
        if (!ldap_state->domain_dn) {
        DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
 
        if (!ldap_state->domain_dn) {
@@ -3463,9 +3526,6 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
                return ntstatus;
        }
 
                return ntstatus;
        }
 
-       attrs[0] = policy_attr;
-       attrs[1] = NULL;
-
        slprintf(value_string, sizeof(value_string) - 1, "%i", value);
 
        smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
        slprintf(value_string, sizeof(value_string) - 1, "%i", value);
 
        smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
@@ -3491,11 +3551,6 @@ 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)
 {
 static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
                                           int policy_index, uint32 value)
 {
-       if (!account_policy_migrated(False)) {
-               return (account_policy_set(policy_index, value)) ?
-                       NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
-       }
-
        return ldapsam_set_account_policy_in_ldap(methods, policy_index,
                                                  value);
 }
        return ldapsam_set_account_policy_in_ldap(methods, policy_index,
                                                  value);
 }
@@ -3584,11 +3639,6 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
 
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
 
-       if (!account_policy_migrated(False)) {
-               return (account_policy_get(policy_index, value))
-                       ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
-       }
-
        if (cache_account_policy_get(policy_index, value)) {
                DEBUG(11,("ldapsam_get_account_policy: got valid value from "
                          "cache\n"));
        if (cache_account_policy_get(policy_index, value)) {
                DEBUG(11,("ldapsam_get_account_policy: got valid value from "
                          "cache\n"));
@@ -3640,7 +3690,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                                    int num_rids,
                                    uint32 *rids,
                                    const char **names,
                                    int num_rids,
                                    uint32 *rids,
                                    const char **names,
-                                   enum SID_NAME_USE *attrs)
+                                   enum lsa_SidType *attrs)
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
@@ -3676,7 +3726,7 @@ 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]);
        for (i=0; i<num_rids; i++) {
                DOM_SID sid;
                sid_compose(&sid, domain_sid, rids[i]);
-               allsids = talloc_asprintf_append(allsids, "(sambaSid=%s)",
+               allsids = talloc_asprintf_append_buffer(allsids, "(sambaSid=%s)",
                                                 sid_string_static(&sid));
                if (allsids == NULL) {
                        goto done;
                                                 sid_string_static(&sid));
                if (allsids == NULL) {
                        goto done;
@@ -3790,7 +3840,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                uint32 rid;
                int rid_index;
                const char *attr;
                uint32 rid;
                int rid_index;
                const char *attr;
-               enum SID_NAME_USE type;
+               enum lsa_SidType type;
                const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
 
                attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
                const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
 
                attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
@@ -3801,7 +3851,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                        continue;
                }
 
                        continue;
                }
 
-               type = atol(attr);
+               type = (enum lsa_SidType)atol(attr);
 
                /* Consistency checks */
                if ((is_builtin && (type != SID_NAME_ALIAS)) ||
 
                /* Consistency checks */
                if ((is_builtin && (type != SID_NAME_ALIAS)) ||
@@ -3928,7 +3978,8 @@ struct ldap_search_state {
 
 static BOOL ldapsam_search_firstpage(struct pdb_search *search)
 {
 
 static BOOL ldapsam_search_firstpage(struct pdb_search *search)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        LDAP *ld;
        int rc = LDAP_OPERATIONS_ERROR;
 
        LDAP *ld;
        int rc = LDAP_OPERATIONS_ERROR;
 
@@ -3980,7 +4031,8 @@ static BOOL ldapsam_search_firstpage(struct pdb_search *search)
 
 static BOOL ldapsam_search_nextpage(struct pdb_search *search)
 {
 
 static BOOL ldapsam_search_nextpage(struct pdb_search *search)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        int rc;
 
        if (!state->connection->paged_results) {
        int rc;
 
        if (!state->connection->paged_results) {
@@ -4010,7 +4062,8 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search)
 static BOOL ldapsam_search_next_entry(struct pdb_search *search,
                                      struct samr_displayentry *entry)
 {
 static BOOL ldapsam_search_next_entry(struct pdb_search *search,
                                      struct samr_displayentry *entry)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        BOOL result;
 
  retry:
        BOOL result;
 
  retry:
@@ -4045,7 +4098,8 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
 
 static void ldapsam_search_end(struct pdb_search *search)
 {
 
 static void ldapsam_search_end(struct pdb_search *search)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        int rc;
 
        if (state->pagedresults_cookie == NULL)
        int rc;
 
        if (state->pagedresults_cookie == NULL)
@@ -4161,7 +4215,8 @@ static BOOL ldapsam_search_users(struct pdb_methods *methods,
                                 struct pdb_search *search,
                                 uint32 acct_flags)
 {
                                 struct pdb_search *search,
                                 uint32 acct_flags)
 {
-       struct ldapsam_privates *ldap_state = methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
        struct ldap_search_state *state;
 
        state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
        struct ldap_search_state *state;
 
        state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
@@ -4317,9 +4372,10 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
 static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
                                     struct pdb_search *search,
                                      const DOM_SID *sid,
 static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
                                     struct pdb_search *search,
                                      const DOM_SID *sid,
-                                    enum SID_NAME_USE type)
+                                    enum lsa_SidType type)
 {
 {
-       struct ldapsam_privates *ldap_state = methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
        struct ldap_search_state *state;
 
        state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
        struct ldap_search_state *state;
 
        state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
@@ -4478,8 +4534,8 @@ static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *ri
        int i;
 
        for (i=0; i<10; i++) {
        int i;
 
        for (i=0; i<10; i++) {
-               NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
-                                                     rid);
+               NTSTATUS result = ldapsam_get_new_rid(
+                       (struct ldapsam_privates *)methods->private_data, rid);
                if (NT_STATUS_IS_OK(result)) {
                        return result;
                }
                if (NT_STATUS_IS_OK(result)) {
                        return result;
                }
@@ -4503,9 +4559,10 @@ static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
 
 static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
                              const DOM_SID *sid,
 
 static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
                              const DOM_SID *sid,
-                             union unid_t *id, enum SID_NAME_USE *type)
+                             union unid_t *id, enum lsa_SidType *type)
 {
 {
-       struct ldapsam_privates *priv = methods->private_data;
+       struct ldapsam_privates *priv =
+               (struct ldapsam_privates *)methods->private_data;
        char *filter;
        const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
                                NULL };
        char *filter;
        const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
                                NULL };
@@ -4565,7 +4622,7 @@ static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
                }
 
                id->gid = strtoul(gid_str, NULL, 10);
                }
 
                id->gid = strtoul(gid_str, NULL, 10);
-               *type = strtoul(value, NULL, 10);
+               *type = (enum lsa_SidType)strtoul(value, NULL, 10);
                ret = True;
                goto done;
        }
                ret = True;
                goto done;
        }
@@ -4741,6 +4798,8 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
 
        if (add_posix) {
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
 
        if (add_posix) {
+               char *escape_name;
+
                DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
 
                /* retrieve the Domain Users group gid */
                DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
 
                /* retrieve the Domain Users group gid */
@@ -4767,12 +4826,21 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                }
                uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
                gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
                }
                uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
                gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+
+               escape_name = escape_rdn_val_string_alloc(name);
+               if (!escape_name) {
+                       DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                if (is_machine) {
                if (is_machine) {
-                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_machine_suffix ());
+                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_machine_suffix ());
                } else {
                } else {
-                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_user_suffix ());
+                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_user_suffix ());
                }
 
                }
 
+               SAFE_FREE(escape_name);
+
                if (!homedir || !shell || !uidstr || !gidstr || !dn) {
                        DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
                        return NT_STATUS_NO_MEMORY;
                if (!homedir || !shell || !uidstr || !gidstr || !dn) {
                        DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
                        return NT_STATUS_NO_MEMORY;
@@ -4954,6 +5022,8 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        }
 
        if (num_result == 0) {
        }
 
        if (num_result == 0) {
+               char *escape_name;
+
                DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
 
                is_new_entry = True;
                DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
 
                is_new_entry = True;
@@ -4965,7 +5035,16 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                }
 
                gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
                }
 
                gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
-               dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, lp_ldap_group_suffix());
+
+               escape_name = escape_rdn_val_string_alloc(name);
+               if (!escape_name) {
+                       DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", escape_name, lp_ldap_group_suffix());
+
+               SAFE_FREE(escape_name);
 
                if (!gidstr || !dn) {
                        DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
 
                if (!gidstr || !dn) {
                        DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
@@ -5303,6 +5382,7 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
        uint32 num_result;
        LDAPMod **mods = NULL;
        char *filter;
        uint32 num_result;
        LDAPMod **mods = NULL;
        char *filter;
+       char *escape_username;
        char *gidstr;
        const char *dn = NULL;
        gid_t gid;
        char *gidstr;
        const char *dn = NULL;
        gid_t gid;
@@ -5319,14 +5399,22 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
                DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
                return NT_STATUS_NO_MEMORY;
        }
                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));
+       if (escape_username== NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
        filter = talloc_asprintf(mem_ctx,
                                 "(&(uid=%s)"
                                 "(objectClass=%s)"
                                 "(objectClass=%s))",
        filter = talloc_asprintf(mem_ctx,
                                 "(&(uid=%s)"
                                 "(objectClass=%s)"
                                 "(objectClass=%s))",
-                                pdb_get_username(sampass),
+                                escape_username,
                                 LDAP_OBJ_POSIXACCOUNT,
                                 LDAP_OBJ_SAMBASAMACCOUNT);
                                 LDAP_OBJ_POSIXACCOUNT,
                                 LDAP_OBJ_SAMBASAMACCOUNT);
+
+       SAFE_FREE(escape_username);
+
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -5382,6 +5470,317 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
        return NT_STATUS_OK;
 }
 
        return NT_STATUS_OK;
 }
 
+
+/**********************************************************************
+ trusted domains functions
+ *********************************************************************/
+
+static char *trusteddom_dn(struct ldapsam_privates *ldap_state,
+                          const char *domain)
+{
+       return talloc_asprintf(talloc_tos(), "sambaDomainName=%s,%s", domain,
+                              ldap_state->domain_dn);
+}
+
+static BOOL get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
+                                 const char *domain, LDAPMessage **entry)
+{
+       int rc;
+       char *filter;
+       int scope = LDAP_SCOPE_SUBTREE;
+       const char **attrs = NULL; /* NULL: get all attrs */
+       int attrsonly = 0; /* 0: return values too */
+       LDAPMessage *result = NULL;
+       char *trusted_dn;
+       uint32 num_result;
+
+       filter = talloc_asprintf(talloc_tos(),
+                                "(&(objectClass=%s)(sambaDomainName=%s))",
+                                LDAP_OBJ_TRUSTDOM_PASSWORD, domain);
+
+       trusted_dn = trusteddom_dn(ldap_state, domain);
+       if (trusted_dn == NULL) {
+               return False;
+       }
+       rc = smbldap_search(ldap_state->smbldap_state, trusted_dn, scope,
+                           filter, attrs, attrsonly, &result);
+
+       if (rc == LDAP_NO_SUCH_OBJECT) {
+               *entry = NULL;
+               return True;
+       }
+
+       if (rc != LDAP_SUCCESS) {
+               return False;
+       }
+
+       num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+       if (num_result > 1) {
+               DEBUG(1, ("ldapsam_get_trusteddom_pw: more than one "
+                         "sambaTrustedDomainPassword object for domain '%s'"
+                         "?!\n", domain));
+               return False;
+       }
+
+       if (num_result == 0) {
+               DEBUG(1, ("ldapsam_get_trusteddom_pw: no "
+                         "sambaTrustedDomainPassword object for domain %s.\n",
+                         domain));
+               *entry = NULL;
+       } else {
+               *entry = ldap_first_entry(priv2ld(ldap_state), result);
+       }
+
+       return True;
+}
+
+static BOOL ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
+                                     const char *domain,
+                                     char** pwd,
+                                     DOM_SID *sid,
+                                     time_t *pass_last_set_time)
+{
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *entry = NULL;
+
+       DEBUG(10, ("ldapsam_get_trusteddom_pw called for domain %s\n", domain));
+
+       if (!get_trusteddom_pw_int(ldap_state, domain, &entry) ||
+           (entry == NULL))
+       {
+               return False;
+       }
+
+       /* password */
+       if (pwd != NULL) {
+               char *pwd_str;
+               pwd_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+                               entry, "sambaClearTextPassword", talloc_tos());
+               if (pwd_str == NULL) {
+                       return False;
+               }
+               /* trusteddom_pw routines do not use talloc yet... */
+               *pwd = SMB_STRDUP(pwd_str);
+               if (*pwd == NULL) {
+                       return False;
+               }
+       }
+
+       /* last change time */
+       if (pass_last_set_time != NULL) {
+               char *time_str;
+               time_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+                               entry, "sambaPwdLastSet", talloc_tos());
+               if (time_str == NULL) {
+                       return False;
+               }
+               *pass_last_set_time = (time_t)atol(time_str);
+       }
+
+       /* domain sid */
+       if (sid != NULL) {
+               char *sid_str;
+               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) {
+                       return False;
+               }
+               sid_copy(sid, dom_sid);
+       }
+
+       return True;
+}
+
+static BOOL ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
+                                     const char* domain,
+                                     const char* pwd,
+                                     const DOM_SID *sid)
+{
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *entry = NULL;
+       LDAPMod **mods = NULL;
+       char *prev_pwd = NULL;
+       char *trusted_dn = NULL;
+       int rc;
+
+       DEBUG(10, ("ldapsam_set_trusteddom_pw called for domain %s\n", domain));
+
+       /*
+        * 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)) {
+               return False;
+       }
+
+       mods = NULL;
+       smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
+                        "sambaTrustedDomainPassword");
+       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)));
+       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());
+               if (prev_pwd != NULL) {
+                       smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+                                        "sambaPreviousClearTextPassword",
+                                        prev_pwd);
+               }
+       }
+
+       trusted_dn = trusteddom_dn(ldap_state, domain);
+       if (trusted_dn == NULL) {
+               return False;
+       }
+       if (entry == NULL) {
+               rc = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
+       } else {
+               rc = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
+       }
+
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(1, ("error writing trusted domain password!\n"));
+               return False;
+       }
+
+       return True;
+}
+
+static BOOL ldapsam_del_trusteddom_pw(struct pdb_methods *methods,
+                                     const char *domain)
+{
+       int rc;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *entry = NULL;
+       const char *trusted_dn;
+
+       if (!get_trusteddom_pw_int(ldap_state, domain, &entry)) {
+               return False;
+       }
+
+       if (entry == NULL) {
+               DEBUG(5, ("ldapsam_del_trusteddom_pw: no such trusted domain: "
+                         "%s\n", domain));
+               return True;
+       }
+
+       trusted_dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state),
+                                      entry);
+       if (trusted_dn == NULL) {
+               DEBUG(0,("ldapsam_del_trusteddom_pw: Out of memory!\n"));
+               return False;
+       }
+
+       rc = smbldap_delete(ldap_state->smbldap_state, trusted_dn);
+       if (rc != LDAP_SUCCESS) {
+               return False;
+       }
+
+       return True;
+}
+
+static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
+                                        TALLOC_CTX *mem_ctx,
+                                        uint32 *num_domains,
+                                        struct trustdom_info ***domains)
+{
+       int rc;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       char *filter;
+       int scope = LDAP_SCOPE_SUBTREE;
+       const char *attrs[] = { "sambaDomainName", "sambaSID", NULL };
+       int attrsonly = 0; /* 0: return values too */
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+
+       filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
+                                LDAP_OBJ_TRUSTDOM_PASSWORD);
+
+       rc = smbldap_search(ldap_state->smbldap_state,
+                           ldap_state->domain_dn,
+                           scope,
+                           filter,
+                           attrs,
+                           attrsonly,
+                           &result);
+
+       if (rc != LDAP_SUCCESS) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       *num_domains = 0;
+       if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
+               DEBUG(1, ("talloc failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (entry = ldap_first_entry(priv2ld(ldap_state), result);
+            entry != NULL;
+            entry = ldap_next_entry(priv2ld(ldap_state), entry))
+       {
+               char *dom_name, *dom_sid_str;
+               struct trustdom_info *dom_info;
+
+               dom_info = TALLOC_P(*domains, struct trustdom_info);
+               if (dom_info == NULL) {
+                       DEBUG(1, ("talloc failed\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               dom_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+                                                          entry,
+                                                          "sambaDomainName",
+                                                          talloc_tos());
+               if (dom_name == NULL) {
+                       DEBUG(1, ("talloc failed\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+               dom_info->name = dom_name;
+
+               dom_sid_str = smbldap_talloc_single_attribute(
+                                       priv2ld(ldap_state), entry, "sambaSID",
+                                       talloc_tos());
+               if (dom_sid_str == NULL) {
+                       DEBUG(1, ("talloc failed\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+               if (!string_to_sid(&dom_info->sid, dom_sid_str)) {
+                       DEBUG(1, ("Error calling string_to_sid on SID %s\n",
+                                 dom_sid_str));
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+
+               ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info,
+                            domains, num_domains);
+
+               if (*domains == NULL) {
+                       DEBUG(1, ("talloc failed\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       DEBUG(5, ("ldapsam_enum_trusteddoms: got %d domains\n", *num_domains));
+       return NT_STATUS_OK;
+}
+
+
 /**********************************************************************
  Housekeeping
  *********************************************************************/
 /**********************************************************************
  Housekeeping
  *********************************************************************/
@@ -5447,6 +5846,11 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
        (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
        (*pdb_method)->new_rid = ldapsam_new_rid;
 
        (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
        (*pdb_method)->new_rid = ldapsam_new_rid;
 
+       (*pdb_method)->get_trusteddom_pw = ldapsam_get_trusteddom_pw;
+       (*pdb_method)->set_trusteddom_pw = ldapsam_set_trusteddom_pw;
+       (*pdb_method)->del_trusteddom_pw = ldapsam_del_trusteddom_pw;
+       (*pdb_method)->enum_trusteddoms = ldapsam_enum_trusteddoms;
+
        /* TODO: Setup private data and free */
 
        if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
        /* TODO: Setup private data and free */
 
        if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
@@ -5454,7 +5858,8 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
                return NT_STATUS_NO_MEMORY;
        }
 
                return NT_STATUS_NO_MEMORY;
        }
 
-       nt_status = smbldap_init(*pdb_method, location, &ldap_state->smbldap_state);
+       nt_status = smbldap_init(*pdb_method, pdb_get_event_context(),
+                                location, &ldap_state->smbldap_state);
 
        if ( !NT_STATUS_IS_OK(nt_status) ) {
                return nt_status;
 
        if ( !NT_STATUS_IS_OK(nt_status) ) {
                return nt_status;
@@ -5481,18 +5886,18 @@ NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *lo
        struct ldapsam_privates *ldap_state;
        char *uri = talloc_strdup( NULL, location );
 
        struct ldapsam_privates *ldap_state;
        char *uri = talloc_strdup( NULL, location );
 
-       if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common( pdb_method, uri ))) {
-               return nt_status;
-       }
-
-       /* the module itself stores a copy of the location so throw this one away */
-
+       trim_char( uri, '\"', '\"' );
+       nt_status = pdb_init_ldapsam_common( pdb_method, uri );
        if ( uri )
                TALLOC_FREE( uri );
 
        if ( uri )
                TALLOC_FREE( uri );
 
+       if ( !NT_STATUS_IS_OK(nt_status) ) {
+               return nt_status;
+       }
+
        (*pdb_method)->name = "ldapsam_compat";
 
        (*pdb_method)->name = "ldapsam_compat";
 
-       ldap_state = (*pdb_method)->private_data;
+       ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
        ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
 
        sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
        ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
 
        sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
@@ -5516,8 +5921,13 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
        DOM_SID secrets_domain_sid;
        pstring domain_sid_string;
        char *dn;
        DOM_SID secrets_domain_sid;
        pstring domain_sid_string;
        char *dn;
+       char *uri = talloc_strdup( NULL, location );
+
+       trim_char( uri, '\"', '\"' );
+       nt_status = pdb_init_ldapsam_common(pdb_method, uri);
+       if ( uri )
+               TALLOC_FREE( uri );
 
 
-       nt_status = pdb_init_ldapsam_common(pdb_method, location);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
@@ -5550,7 +5960,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                }
        }
 
                }
        }
 
-       ldap_state = (*pdb_method)->private_data;
+       ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
        ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
 
        /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
        ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
 
        /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
@@ -5583,6 +5993,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
 
        dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
        if (!dn) {
 
        dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
        if (!dn) {
+               ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -5599,6 +6010,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
                        DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
                                  "read as a valid SID\n", domain_sid_string));
                if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
                        DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
                                  "read as a valid SID\n", domain_sid_string));
+                       ldap_msgfree(result);
                        return NT_STATUS_INVALID_PARAMETER;
                }
                found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
                        return NT_STATUS_INVALID_PARAMETER;
                }
                found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,