diff --git a/lib/api/kolab_api_service_domain.php b/lib/api/kolab_api_service_domain.php
index 9781eeb..8803109 100644
--- a/lib/api/kolab_api_service_domain.php
+++ b/lib/api/kolab_api_service_domain.php
@@ -1,422 +1,445 @@
 <?php
 /*
  +--------------------------------------------------------------------------+
  | This file is part of the Kolab Web Admin Panel                           |
  |                                                                          |
  | Copyright (C) 2011-2012, Kolab Systems AG                                |
  |                                                                          |
  | This program is free software: you can redistribute it and/or modify     |
  | it under the terms of the GNU Affero 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 Affero General Public License for more details.                      |
  |                                                                          |
  | You should have received a copy of the GNU Affero General Public License |
  | along with this program. If not, see <http://www.gnu.org/licenses/>      |
  +--------------------------------------------------------------------------+
  | Author: Aleksander Machniak <machniak@kolabsys.com>                      |
  | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>                     |
  +--------------------------------------------------------------------------+
 */
 
 /**
  * Service providing domain mutations
  */
 class kolab_api_service_domain extends kolab_api_service
 {
 
     /**
      * Returns service capabilities.
      *
      * @param string $domain Domain name
      *
      * @return array Capabilities list
      */
     public function capabilities($domain)
     {
         $auth = Auth::get_instance();
         $conf = Conf::get_instance();
 
         $domain_base_dn = $conf->get('domain_base_dn');
 
         if (empty($domain_base_dn)) {
             return array();
         }
 
         $effective_rights = $auth->list_rights($domain_base_dn);
         $rights           = array();
 
         if (in_array('add', $effective_rights['entrylevelrights'])) {
             $rights['add'] = "w";
         }
 
         if (in_array('delete', $effective_rights['entrylevelrights'])) {
             $rights['delete'] = "w";
         }
 
         if (in_array('modrdn', $effective_rights['entrylevelrights'])) {
             $rights['edit'] = "w";
         }
 
         if (in_array('read', $effective_rights['entrylevelrights'])) {
             $rights['find'] = "r";
             $rights['info'] = "r";
         }
 
         $rights['effective_rights'] = "r";
 
         return $rights;
     }
 
     public function domain_add($getdata, $postdata)
     {
         Log::trace("domain.add(\$getdata = " . var_export($getdata, TRUE) . ", \$postdata = " . var_export($postdata, TRUE) . ")");
 
         $conf = Conf::get_instance();
         $dna  = $conf->get('domain_name_attribute');
 
         if (empty($dna)) {
             $dna = 'associateddomain';
         }
 
         if (empty($postdata[$dna])) {
             Log::error("domain.add called without '" . $dna . "' specified");
             return false;
         }
 
         $auth = Auth::get_instance($conf->get('kolab', 'primary_domain'));
 
         // parse input attributes
         $attributes       = $this->parse_input_attributes('domain', $postdata);
         $attributes[$dna] = (array) $attributes[$dna];
         $domain           = array_shift($attributes[$dna]);
 
         $this->_mod_domain_attrs($domain, $attributes);
 
         $result = $auth->domain_add($domain, $attributes);
 
         if ($result) {
             if ($id = $this->unique_attribute_value($result)) {
                 $attributes['id'] = $id;
             }
 
 
             $this->_after_domain_created($attributes, $domain);
 
             return $attributes;
         }
 
         return false;
     }
 
     /**
      * Domain delete.
      *
      * @param array $get  GET parameters
      * @param array $post POST parameters
      *
      * @return bool True on success, False on failure
      * @throws kolab_api_exception
      */
     public function domain_delete($getdata, $postdata)
     {
         Log::trace("domain.delete(\$getdata = '" . var_export($getdata, TRUE) . "', \$postdata = '" . var_export($postdata, TRUE) . "')");
 
         if (empty($postdata['id'])) {
             Log::error("domain.delete called without a Domain ID");
             return false;
         }
 
         $auth = Auth::get_instance();
 
         // check if domain is empty
         if (empty($postdata['force']) || strtolower($postdata['force']) == 'false') {
             if (!$auth->domain_is_empty($postdata['id'])) {
                 throw new kolab_api_exception(kolab_api_exception::DOMAIN_NOT_EMPTY);
             }
         }
 
         $result = $auth->domain_delete($postdata['id']);
 
         if ($result) {
             return $result;
         }
 
         return false;
     }
 
     public function domain_edit($getdata, $postdata)
     {
         Log::trace("domain.edit(\$getdata = '" . var_export($getdata, TRUE) . "', \$postdata = '" . var_export($postdata, TRUE) . "')");
 
         if (empty($postdata['id'])) {
             Log::error("domain.edit called without a Domain ID");
             return false;
         }
 
         $auth = Auth::get_instance();
 
         // check if domain is empty when changing status to deleted, as in domain.delete
         if ($postdata['inetdomainstatus'] == 'deleted'
             && (empty($postdata['force']) || strtolower($postdata['force']) == 'false')
         ) {
             $domain = $auth->domain_info($postdata['id']);
             if (!empty($domain) && $domain[key($domain)]['inetdomainstatus'] != 'deleted'
                 && !$auth->domain_is_empty($domain)
             ) {
                 throw new kolab_api_exception(kolab_api_exception::DOMAIN_NOT_EMPTY);
             }
         }
 
         $attributes = $this->parse_input_attributes('domain', $postdata, $postdata['type_id']);
 
-        $this->_mod_domain_attrs(null, $attributes);
+        $this->_mod_domain_attrs(null, $attributes, $postdata['id']);
 
         $result = $auth->domain_edit($postdata['id'], $attributes, $postdata['type_id']);
 
         if ($result) {
             return $result;
         }
 
         return false;
     }
 
     public function domain_effective_rights($getdata, $postdata)
     {
         $auth = Auth::get_instance();
         $conf = Conf::get_instance();
         $dna  = $conf->get('domain_name_attribute');
 
         if (empty($dna)) {
             $dna = 'associateddomain';
         }
 
         // TODO: Input validation
         if (!empty($getdata[$dna])) {
             $entry_dn    = $getdata[$dna];
             $unique_attr = self::unique_attribute();
             $domain      = $auth->domain_find_by_attribute(array($unique_attr => $entry_dn));
 
             if (!empty($domain)) {
                 $entry_dn = key($domain);
             }
         }
         else {
             $entry_dn = $conf->get('ldap', 'domain_base_dn');
         }
 
         // TODO: Fix searching the correct base_dn... Perhaps find the entry
         // first.
         $effective_rights = $auth->list_rights($entry_dn);
 
         return $effective_rights;
     }
 
     public function domain_find($getdata, $postdata)
     {
         $conf = Conf::get_instance();
         $dna  = $conf->get('domain_name_attribute');
 
         if (empty($dna)) {
             $dna = 'associateddomain';
         }
 
         if (empty($getdata[$dna])) {
             Log::error("domain.find called without a '" . $dna . "' parameter");
             return false;
         }
 
         $auth   = Auth::get_instance();
         $domain = $auth->domain_find_by_attribute(array($dna => $getdata[$dna]));
 
         if (!empty($domain)) {
             return $domain;
         }
 
         return false;
     }
 
     /**
      * Domain information.
      *
      * @param array $get   GET parameters
      * @param array $post  POST parameters
      *
      * @return array|bool Domain attributes, False on error
      */
     public function domain_info($getdata, $postdata)
     {
         Log::trace("domain.info(\$getdata = '" . var_export($getdata, TRUE) . "', \$postdata = '" . var_export($postdata, TRUE) . "')");
 
         if (empty($getdata['id'])) {
             Log::error("domain.info called without a Domain ID");
             return false;
         }
 
         $auth   = Auth::get_instance();
         $attrs  = $this->object_attributes('domain');
         $result = $auth->domain_info($getdata['id'], $attrs);
 
         // normalize result
         $result = $this->parse_result_attributes('domain', $result);
 
         if (empty($result['id'])) {
             $result['id'] = $getdata['id'];
         }
 
         if ($result) {
             return $result;
         }
 
         return false;
     }
 
     /**
      * Modify hosted domain attributes
      */
-    protected function _mod_domain_attrs($domain, &$attributes)
+    protected function _mod_domain_attrs($domain, &$attributes, $olddn = null)
     {
         // Generate attributes (aci, inetdomainbasedn) for hosted domains
         $conf = Conf::get_instance();
         if ($conf->get('kolab_wap', 'hosted_root_dn')) {
 
             $domain_name_attribute = $conf->get('ldap', 'domain_name_attribute');
             $hosted_root_dn        = $conf->get('kolab_wap', 'hosted_root_dn');
             $mgmt_root_dn          = $conf->get('kolab_wap', 'mgmt_root_dn');
 
             if (empty($mgmt_root_dn)) {
                 $mgmt_root_dn = $conf->get('root_dn');
             }
 
             if (empty($domain_name_attribute)) {
                 $domain_name_attribute = 'associateddomain';
             }
 
             if (!is_array($attributes[$domain_name_attribute])) {
                 $attributes[$domain_name_attribute] = (array) $attributes[$domain_name_attribute];
             }
 
             if (empty($domain)) {
                 $domain = $attributes[$domain_name_attribute][0];
             }
 
             if (!in_array($domain, $attributes[$domain_name_attribute])) {
                 array_unshift($attributes[$domain_name_attribute], $domain);
             }
 
             $domain_root_dn = 'ou=' . $domain . ',' . $hosted_root_dn;
 
             $aci  = array(
                 '(targetattr = "*")'
                 . '(version 3.0; acl "Deny Unauthorized"; deny (all)'
                 . '(userdn != "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . ' || '
                 . 'ldap:///ou=People,' . $domain_root_dn . '??sub?(objectclass=inetorgperson)") AND NOT '
                 . 'roledn = "ldap:///cn=kolab-admin,' . $mgmt_root_dn . '";)',
 
                 '(targetattr != "userPassword")'
                 . '(version 3.0;acl "Search Access";allow (read,compare,search)'
                 . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . ' || '
                 . 'ldap:///ou=People,' . $domain_root_dn . '??sub?(objectclass=inetorgperson)");)',
 
                 '(targetattr = "*")'
                 . '(version 3.0;acl "Kolab Administrators";allow (all)'
                 . '(roledn = "ldap:///cn=kolab-admin,' . $domain_root_dn . ' || '
                 . 'ldap:///cn=kolab-admin,' . $mgmt_root_dn . '");)'
             );
 
-            $attributes['aci']              = $aci;
-            $attributes['inetdomainbasedn'] = $domain_root_dn;
+            // Preserve important old aci and inetdomainbasedn attributes of the
+            // management and hosted domain.
+            if (!empty($olddn)) {
+                $auth = Auth::get_instance();
+                $info = $auth->domain_info($olddn);
+                if (!empty($info)) {
+                    $oldattributes = reset($info);
+                    if (!empty($oldattributes['inetdomainbasedn'])
+                        && $oldattributes['inetdomainbasedn'] == $hosted_root_dn
+                        || "dc=".implode(",dc=",explode(".",$domain)) == $mgmt_root_dn
+                    ) {
+                        $aci = $oldattributes['aci'];
+                        if (!empty($oldattributes['inetdomainbasedn'])) {
+                            $domain_root_dn = $oldattributes['inetdomainbasedn'];
+                        } else {
+                            $domain_root_dn = null;
+                        }
+                    }
+                }
+            }
+
+            $attributes['aci'] = $aci;
+            if (!empty($domain_root_dn)) {
+                $attributes['inetdomainbasedn'] = $domain_root_dn;
+            }
 
             $this->is_hosted = true;
         }
     }
 
     /**
      * Create LDAP object related to the new hosted domain
      */
     protected function _after_domain_created($attributes, $domain)
     {
         if (!$this->is_hosted) {
             return;
         }
 
         $conf         = Conf::get_instance();
         $ou_service   = $this->controller->get_service('ou');
         $role_service = $this->controller->get_service('role');
 
         $hosted_root_dn = $conf->get('kolab_wap', 'hosted_root_dn');
         $mgmt_root_dn   = $conf->get('kolab_wap', 'mgmt_root_dn');
         $domain_root_dn = 'ou=' . $domain . ',' . $hosted_root_dn;
 
         if (empty($mgmt_root_dn)) {
             $mgmt_root_dn = $conf->get('root_dn');
         }
 
         $ou_domain = array(
             'ou'            => $domain,
             'base_dn'       => $hosted_root_dn,
             'description'   => $domain,
             'type_id'       => 1,
         );
 
         $ou_domain['aci'] = array(
             '(targetattr = "*")'
             . '(version 3.0;acl "Deny Unauthorized"; deny (all)'
             . '(userdn != "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . ' || '
             . 'ldap:///ou=People,' . $domain_root_dn . '??sub?(objectclass=inetorgperson)") AND NOT '
             . 'roledn = "ldap:///cn=kolab-admin,' . $mgmt_root_dn . '";)',
 
             '(targetattr != "userPassword")'
             . '(version 3.0;acl "Search Access";allow (read,compare,search,write)'
             . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . ' || '
             . 'ldap:///ou=People,' . $domain_root_dn . '??sub?(objectclass=inetorgperson)");)',
 
             '(targetattr = "*")'
             . '(version 3.0;acl "Kolab Administrators";allow (all)'
             . '(roledn = "ldap:///cn=kolab-admin,' . $domain_root_dn . ' || '
             . 'ldap:///cn=kolab-admin,' . $mgmt_root_dn . '");)',
 
             '(target = "ldap:///ou=*,' . $domain_root_dn . '")(targetattr="objectclass || aci || ou")'
             . '(version 3.0;acl "Allow Domain sub-OU Registration"; allow (add)'
             . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . '");)',
 
             '(target = "ldap:///uid=*,ou=People,' . $domain_root_dn . '")(targetattr="*")'
             . '(version 3.0;acl "Allow Domain First User Registration"; allow (add)'
             . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . '");)',
 
             '(target = "ldap:///cn=*,' . $domain_root_dn . '")(targetattr="objectclass || cn")'
             . '(version 3.0;acl "Allow Domain Role Registration"; allow (add)'
             . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . '");)',
         );
 
         $ou_service->ou_add(null, $ou_domain);
 
         // Add OU trees
 
         foreach (array('Groups', 'People', 'Resources', 'Shared Folders') as $item) {
             $ou = array(
                 'ou'            => $item,
                 'base_dn'       => $domain_root_dn,
                 'type_id'       => 1,
                 'description'   => $item,
             );
 
             $ou_service->ou_add(null, $ou);
         }
 
         // Add an admin role
 
         $role = array(
             'cn'            => 'kolab-admin',
             'description'   => 'Domain Administrator',
             'type_id'       => 1,
             'base_dn'       => $domain_root_dn,
         );
 
         $role_service->role_add(null, $role);
     }
 }