diff --git a/include/class_pluglist.inc b/include/class_pluglist.inc
index dc019fba5dedd9de3800b9fb317aafbbc0213007..8504665ca3f4cd5d0b398747ee1ad2f9752d3490 100644
--- a/include/class_pluglist.inc
+++ b/include/class_pluglist.inc
@@ -42,6 +42,11 @@ class pluglist {
    */
   var $info             = array();
 
+  /*!
+   * \brief Foreign references on DNs
+   */
+  var $dnForeignRefs = array();
+
   /*!
    * \brief Using the plugin index as a key, the class of the plugin.
    */
@@ -123,6 +128,9 @@ class pluglist {
                 $foreign_refs[$class][$field] = array();
               }
               $foreign_refs[$class][$field][] = array($cname, $ofield, $filter);
+              if ($field == 'dn') {
+                $this->dnForeignRefs[] = array($cname, $ofield, $filter, (isset($pfk[3]) ? $pfk[3] : "$ofield=*%oldvalue%"));
+              }
             }
             unset($pfk);
           }
diff --git a/include/simpleplugin/attributes/class_SetAttribute.inc b/include/simpleplugin/attributes/class_SetAttribute.inc
index 7871fcf64e2405af8995f0e441292e0d4dd73efb..f27f3c5df3c2590ebae0c11c6b4c30b8bd4d58c1 100644
--- a/include/simpleplugin/attributes/class_SetAttribute.inc
+++ b/include/simpleplugin/attributes/class_SetAttribute.inc
@@ -317,7 +317,15 @@ class SetAttribute extends Attribute
   function foreignKeyUpdate($oldvalue, $newvalue, $source)
   {
     foreach ($this->value as $key => &$value) {
-      if ($value == $oldvalue) {
+      if (($source['FIELD'] == 'dn') && ($source['MODE'] == 'move')) {
+        if ($newvalue === NULL) {
+          if (preg_match('/'.preg_quote($oldvalue, '/').'$/', $value)) {
+            unset($this->value[$key]);
+          }
+        } else {
+          $value = preg_replace('/'.preg_quote($oldvalue, '/').'$/', $newvalue, $value);
+        }
+      } elseif ($value == $oldvalue) {
         if ($newvalue === NULL) {
           unset($this->value[$key]);
         } elseif ($source['MODE'] == 'copy') {
diff --git a/include/simpleplugin/class_Attribute.inc b/include/simpleplugin/class_Attribute.inc
index 65b24789163b186909fcf31268ced3f92fb9f3e2..730b2a82a87e2a486090e3073ac032004b09810c 100644
--- a/include/simpleplugin/class_Attribute.inc
+++ b/include/simpleplugin/class_Attribute.inc
@@ -710,7 +710,13 @@ class Attribute
   function foreignKeyUpdate($oldvalue, $newvalue, $source)
   {
     if ($source['MODE'] == 'move') {
-      if ($this->getValue() == $oldvalue) {
+      if ($source['FIELD'] == 'dn') {
+        $value = $this->getValue();
+        $value = preg_replace('/'.preg_quote($oldvalue, '/').'$/', $newvalue, $value, -1, $count);
+        if ($count > 0) {
+          $this->setValue($value);
+        }
+      } elseif ($this->getValue() == $oldvalue) {
         $this->setValue($newvalue);
       }
     }
diff --git a/include/simpleplugin/class_dialogAttributes.inc b/include/simpleplugin/class_dialogAttributes.inc
index d09bf46f76859207d198ef268af4102f3e5aa340..6e7b47a533719657b05e3fdf9ec9f06ab5d6a50b 100644
--- a/include/simpleplugin/class_dialogAttributes.inc
+++ b/include/simpleplugin/class_dialogAttributes.inc
@@ -446,7 +446,19 @@ class GenericDialogAttribute extends DialogAttribute
   function foreignKeyUpdate($oldvalue, $newvalue, $source)
   {
     foreach ($this->value as $key => &$value) {
-      if ($value == $oldvalue) {
+      if (($source['FIELD'] == 'dn') && ($source['MODE'] == 'move')) {
+        if ($newvalue === NULL) {
+          if (preg_match('/'.preg_quote($oldvalue, '/').'$/', $value)) {
+            $this->removeValue($key);
+          }
+        } else {
+          $value = preg_replace('/'.preg_quote($oldvalue, '/').'$/', $newvalue, $value, -1, $count);
+          if ($count > 0) {
+            /* Update display */
+            $this->fillDisplayValue($key);
+          }
+        }
+      } elseif ($value == $oldvalue) {
         if ($newvalue === NULL) {
           $this->removeValue($key);
         } elseif ($source['MODE'] == 'copy') {
diff --git a/include/simpleplugin/class_simplePlugin.inc b/include/simpleplugin/class_simplePlugin.inc
index 097f6db82bc7aba0faf9f1a0ff47862fe01fbc59..450e220af375092f37c6d0e5ac4addf90e6810a3 100644
--- a/include/simpleplugin/class_simplePlugin.inc
+++ b/include/simpleplugin/class_simplePlugin.inc
@@ -1536,15 +1536,64 @@ class simplePlugin
 
   function browseForeignKeys($mode, $param1 = NULL, $param2 = NULL)
   {
+    global $plist;
     if (preg_match('/^handle_/', $mode)) {
       $olddn    = $param1;
       $newdn    = $param2;
       $classes  = array(get_class($this));
+      $subobjects = ($olddn != $newdn); //FIXME
     } elseif ($mode == 'references') {
       $classes = array_keys($this->parent->by_object);
     }
-    // We group by objetType concerned
+    // We group by objectType concerned
     $foreignRefs = array();
+    if ($subobjects) {
+      $field = 'dn';
+      /* Special treatment for foreign keys on DN when moving an object
+       * All references on DN are treated on subobjects */
+      foreach ($plist->dnForeignRefs as $ref) {
+        $class      = $ref[0];
+        $ofield     = $ref[1];
+        $filter     = $ref[2];
+        $filtersub  = $ref[3];
+        if ($class == 'aclAssignment') {
+          /* Special case: aclAssignment foreignKey is ignored on department types as it’s handled by the aclAssignment objectType */
+          $objectTypes = array('ACLASSIGNMENT');
+        } elseif (is_subclass_of($class, 'simpleService')) {
+          $objectTypes = array('SERVER');
+        } else {
+          $objectTypes = array();
+          $cinfos = pluglist::pluginInfos($class);
+          foreach ($cinfos['plObjectType'] as $key => $objectType) {
+            if (!is_numeric($key)) {
+              $objectType = $key;
+            }
+            if (preg_match('/^ogroup-/i', $objectType)) {
+              $objectType = 'OGROUP';
+            }
+            $objectTypes[] = $objectType;
+          }
+          $objectTypes = array_unique($objectTypes);
+        }
+        foreach ($objectTypes as $objectType) {
+          $oldvalue = $olddn;
+          $newvalue = $newdn;
+
+          $foreignRefs[$objectType]['refs'][$class][$ofield][$field] =
+            array(
+              'tab'       => $classes[0],
+              'field'     => $field,
+              'oldvalue'  => $oldvalue,
+              'newvalue'  => $newvalue,
+            );
+          $filter = templateHandling::parseString($filtersub, array('oldvalue' => $oldvalue, 'newvalue' => $newvalue), 'ldap_escape_f');
+          if (!preg_match('/^\(.*\)$/', $filter)) {
+            $filter = '('.$filter.')';
+          }
+          $foreignRefs[$objectType]['filters'][$filter] = $filter;
+        }
+      }
+    }
     foreach ($classes as $tabclass) {
       $infos = pluglist::pluginInfos($tabclass);
       foreach ($infos['plForeignRefs'] as $field => $refs) {
diff --git a/plugins/admin/acl/class_aclAssignment.inc b/plugins/admin/acl/class_aclAssignment.inc
index 19c59043b41bb47965a77e90ec8bc424ce5edad3..fd4667fca9f92d195d3cfb26a3d4ff119014ac2b 100644
--- a/plugins/admin/acl/class_aclAssignment.inc
+++ b/plugins/admin/acl/class_aclAssignment.inc
@@ -211,11 +211,23 @@ class ACLsAssignmentAttribute extends DialogOrderedArrayAttribute
   function foreignKeyUpdate($oldvalue, $newvalue, $source)
   {
     foreach ($this->value as $key => &$value) {
-      if (($source['CLASS'] == 'aclRole') && ($value['role'] == $oldvalue) && ($source['MODE'] != 'copy')) {
+      if (($source['FIELD'] == 'dn') && ($source['MODE'] == 'move')) {
         if ($newvalue === NULL) {
-          unset($this->value[$key]);
+          if (preg_match('/'.preg_quote($oldvalue, '/').'$/', $value['role'])) {
+            unset($this->value[$key]);
+          }
+          foreach ($value['members'] as $member_key => $member) {
+            if (preg_match('/'.preg_quote($oldvalue, '/').'$/', $member)) {
+              unset($value['members'][$member_key]);
+            }
+          }
+          unset($member);
         } else {
-          $value['role'] = $newvalue;
+          $value['role'] = preg_replace('/'.preg_quote($oldvalue, '/').'$/', $newvalue, $value['role']);
+          foreach ($value['members'] as &$member) {
+            $member = preg_replace('/'.preg_quote($oldvalue, '/').'$/', $newvalue, $member);
+          }
+          unset($member);
         }
       } elseif (in_array($source['CLASS'], array('user','posixGroup','roleGeneric')) && (($member_key = array_search($oldvalue, $value['members'])) !== FALSE)) {
         if ($newvalue === NULL) {
@@ -275,10 +287,10 @@ class aclAssignment extends simplePlugin
       'plObjectType'  => $oc,
       'plForeignKeys'  => array(
         'gosaAclEntry' => array(
-          array('aclRole',      'dn', 'gosaAclEntry=*:*:%b|oldvalue%:*'),
-          array('user',         'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*'),
-          array('posixGroup',   'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*'),
-          array('roleGeneric',  'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*'),
+          array('aclRole',      'dn', 'gosaAclEntry=*:*:%b|oldvalue%:*',    'gosaAclEntry=*'),
+          array('user',         'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*',  'gosaAclEntry=*'),
+          array('posixGroup',   'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*',  'gosaAclEntry=*'),
+          array('roleGeneric',  'dn', 'gosaAclEntry=*:*:*:*%b|oldvalue%*',  'gosaAclEntry=*'),
         )
       ),