diff --git a/include/class_ldap.inc b/include/class_ldap.inc
index 7f12ee8cf862015ffa3453b48ed1e301defb94e1..427be0ee34e6f0e388681f1a5888ebf0fe0f1083 100644
--- a/include/class_ldap.inc
+++ b/include/class_ldap.inc
@@ -309,7 +309,7 @@ class LDAP
    *
    * \param string $scope Scope of the search: subtree/base/one
    */
-  function search ($srp, $filter, $attrs = [], $scope = 'subtree')
+  function search ($srp, $filter, $attrs = [], $scope = 'subtree', array $controls = NULL)
   {
     if ($this->hascon) {
       if ($this->reconnect) {
@@ -320,14 +320,26 @@ class LDAP
       $this->clearResult($srp);
       switch (strtolower($scope)) {
         case 'base':
-          $this->sr[$srp] = @ldap_read($this->cid, $this->basedn, $filter, $attrs);
+          if (isset($controls)) {
+            $this->sr[$srp] = @ldap_read($this->cid, $this->basedn, $filter, $attrs, 0, 0, 0, LDAP_DEREF_NEVER, $controls);
+          } else {
+            $this->sr[$srp] = @ldap_read($this->cid, $this->basedn, $filter, $attrs);
+          }
           break;
         case 'one':
-          $this->sr[$srp] = @ldap_list($this->cid, $this->basedn, $filter, $attrs);
+          if (isset($controls)) {
+            $this->sr[$srp] = @ldap_list($this->cid, $this->basedn, $filter, $attrs, 0, 0, 0, LDAP_DEREF_NEVER, $controls);
+          } else {
+            $this->sr[$srp] = @ldap_list($this->cid, $this->basedn, $filter, $attrs);
+          }
           break;
         case 'subtree':
         default:
-          $this->sr[$srp] = @ldap_search($this->cid, $this->basedn, $filter, $attrs);
+          if (isset($controls)) {
+            $this->sr[$srp] = @ldap_search($this->cid, $this->basedn, $filter, $attrs, 0, 0, 0, LDAP_DEREF_NEVER, $controls);
+          } else {
+            $this->sr[$srp] = @ldap_search($this->cid, $this->basedn, $filter, $attrs);
+          }
           break;
       }
       $this->error = @ldap_error($this->cid);
@@ -348,6 +360,21 @@ class LDAP
     }
   }
 
+  /*!
+   * \brief Parse last result
+   *
+   * \param integer $srp srp
+   *
+   */
+  function parse_result ($srp, &$errcode, &$matcheddn, &$errmsg, &$referrals, &$controls): bool
+  {
+    if ($this->hascon && $this->hasres[$srp]) {
+      return @ldap_parse_result($this->cid, $this->sr[$srp], $errcode, $matcheddn, $errmsg, $referrals, $controls);
+    }
+
+    return FALSE;
+  }
+
   /*
    * \brief List
    *
diff --git a/include/class_ldapMultiplexer.inc b/include/class_ldapMultiplexer.inc
index 9bbae6a8bfe1c0fc461f037fce861acb91f7cfce..6cb5c86d3ba7b682c3249400b90b94b9e6d06c42 100644
--- a/include/class_ldapMultiplexer.inc
+++ b/include/class_ldapMultiplexer.inc
@@ -61,7 +61,7 @@ class ldapMultiplexer
   public function __call ($methodName, $parameters)
   {
     /* Add resource pointer if the mentioned methods are used */
-    if (in_array($methodName, ['search','ls','cat','fetch','clearResult','resetResult','count','getDN','rmdir_recursive','create_missing_trees','import_single_entry','import_complete_ldif'])) {
+    if (in_array($methodName, ['search','ls','cat','fetch','clearResult','resetResult','count','getDN','rmdir_recursive','create_missing_trees','import_single_entry','import_complete_ldif','parse_result'])) {
       array_unshift($parameters, $this->sr);
     }
 
diff --git a/setup/class_setupStepMigrate.inc b/setup/class_setupStepMigrate.inc
index 908753ce5b2a878b33de9f191a07fea4bc2184f7..1b868556740b922495db8faa4c18f258f309b2db 100644
--- a/setup/class_setupStepMigrate.inc
+++ b/setup/class_setupStepMigrate.inc
@@ -974,13 +974,6 @@ class setupStepMigrate extends setupStep
     /***********
      * Search for all users
      ***********/
-    $res = $ldap->search('(&(objectClass=inetOrgPerson)(!(uid=*$)))', ['dn']);
-    if (!$res) {
-      throw new CheckFailedException(
-        _('LDAP query failed'),
-        _('Possibly the "root object" is missing.')
-      );
-    }
     $sizeLimitHit = FALSE;
 
     /***********
@@ -988,24 +981,56 @@ class setupStepMigrate extends setupStep
      ***********/
     $this->outsideUsers_toMigrate = [];
     $people_ou = trim(get_ou('userRDN'));
+    $cookie = '';
 
-    while ($attrs = $ldap->fetch()) {
-      $people_db_base = preg_replace('/^[^,]+,'.preg_quote($people_ou, '/').'/i', '', $attrs['dn']);
+    do {
+      $res = $ldap->search('(&(objectClass=inetOrgPerson)(!(uid=*$)))', ['dn'], 0, 0, 0, LDAP_DEREF_NEVER,
+        [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 500, 'cookie' => $cookie]]]
+      );
+      if (!$res) {
+        throw new CheckFailedException(
+          _('LDAP query failed'),
+          _('Possibly the "root object" is missing.')
+        );
+      }
+      if (!$ldap->parse_result($errcode, $matcheddn, $errmsg, $referrals, $controls)) {
+        throw new CheckFailedException(
+          _('LDAP result parsing failed'),
+          _('LDAP result parsing failed')
+        );
+      }
+      if ($errcode !== 0) {
+        throw new CheckFailedException(
+          _('LDAP error'),
+          $errmsg
+        );
+      }
+      if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) {
+        // You need to pass the cookie from the last call to the next one
+        $cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'];
+      } else {
+        $cookie = '';
+      }
 
-      /* Check if entry is not an addressbook only user
-       *  and verify that he is in a valid department
-       */
-      if (!preg_match('/dc=addressbook,/', $people_db_base) &&
-          !in_array($people_db_base, $config->getDepartmentList())) {
-        $attrs['checked'] = FALSE;
-        $attrs['ldif']    = '';
-        $this->outsideUsers_toMigrate[base64_encode($attrs['dn'])] = $attrs;
-        if (count($this->outsideUsers_toMigrate) >= static::$objectNumberLimit) {
-          $sizeLimitHit = TRUE;
-          break;
+      while ($attrs = $ldap->fetch()) {
+        $people_db_base = preg_replace('/^[^,]+,'.preg_quote($people_ou, '/').'/i', '', $attrs['dn']);
+
+        /* Check if entry is not an addressbook only user
+         *  and verify that he is in a valid department
+         */
+        if (!preg_match('/dc=addressbook,/', $people_db_base) &&
+            !in_array($people_db_base, $config->getDepartmentList())) {
+          $attrs['checked'] = FALSE;
+          $attrs['ldif']    = '';
+          $this->outsideUsers_toMigrate[base64_encode($attrs['dn'])] = $attrs;
+          if (count($this->outsideUsers_toMigrate) >= static::$objectNumberLimit) {
+            $sizeLimitHit = TRUE;
+            break 2;
+          }
         }
       }
-    }
+      // Empty cookie means last page
+    } while (!empty($cookie));
 
     if (count($this->outsideUsers_toMigrate) == 0) {
       return '';