由于我没有找到任何干净的解决方案,我决定采用第一种方法:通过对象Sids过滤。
此变通方法有它的局限性:
- 它仅适用于物体与的objectSID,即用户和组。
- 它假设所有用户/组都由相同的权限创建。
- 它假定不存在比大小限制更多的丢失相对SID。
这个想法是先读取所有可能的对象,然后选出具有最低相对SID的对象。相对SID是在SID的最后一个块:
S-1-5-21-3188256696-111411151-3922474875-
让我们假设这是一个搜索最低相对SID,只有返回'部分搜索结果'。 让我们进一步假设的大小限制为1000
程序然后执行以下操作: 它搜索
S-1-5-21-3188256696-111411151-3922474875- 1158之间与SID的所有对象
和
S-1-5-21-3188256696-111411151-3922474875-
然后所有之间
个
S-1-5-21-3188256696-111411151-3922474875-
和
S-1-5-21-3188256696-111411151-3922474875-
等等,直到一个的搜索返回零对象。
这种方法有几个问题,但对我的目的来说就足够了。
守则:
$filter = '(objectClass=Group)';
$attributes = array('objectsid','cn'); //objectsid needs to be set
$result = array();
$maxPageSize = 1000;
$searchStep = $maxPageSize-1;
$adResult = @$adConn->search($filter,$attributes); //Supress warning for first query (because it exceeds the size limit)
//Read smallest RID from the resultset
$minGroupRID = '';
for($i=0;$i<$adResult['count'];$i++){
$groupRID = unpack('V',substr($adResult[$i]['objectsid'][0],24));
if($minGroupRID == '' || $minGroupRID>$groupRID[1]){
$minGroupRID = $groupRID[1];
}
}
$sidPrefix = substr($adResult[$i-1]['objectsid'][0],0,24); //Read last objectsid and cut off the prefix
$nextStepGroupRID = $minGroupRID;
do{ //Search for all objects with a lower objectsid than minGroupRID
$adResult = $adConn->search('(&'.$filter.'(objectsid<='.preg_replace('/../','\\\\$0',bin2hex($sidPrefix.pack('V',$nextStepGroupRID))).')(objectsid>='.preg_replace('/../','\\\\$0',bin2hex($sidPrefix.pack('V',$nextStepGroupRID-$searchStep))).'))', $attributes);
for($i=0;$i<$adResult['count'];$i++){
$RID = unpack('V',substr($adResult[$i]['objectsid'][0],24)); //Extract the relative SID from the SID
$RIDs[] = $RID[1];
$resultSet = array();
foreach($attributes as $attribute){
$resultSet[$attribute] = $adResult[$i][$attribute][0];
}
$result[$RID[1]] = $resultSet;
}
$nextStepGroupRID = $nextStepGroupRID-$searchStep;
}while($adResult['count']>1);
$nextStepGroupRID = $minGroupRID;
do{ //Search for all object with a higher objectsid than minGroupRID
$adResult = $adConn->search('(&'.$filter.'(objectsid>='.preg_replace('/../','\\\\$0',bin2hex($sidPrefix.pack('V',$nextStepGroupRID))).')(objectsid<='.preg_replace('/../','\\\\$0',bin2hex($sidPrefix.pack('V',$nextStepGroupRID+$searchStep))).'))', $attributes);
for($i=0;$i<$adResult['count'];$i++){
$RID = unpack('V',substr($adResult[$i]['objectsid'][0],24)); //Extract the relative SID from the SID
$RIDs[] = $RID[1];
$resultSet = array();
foreach($attributes as $attribute){
$resultSet[$attribute] = $adResult[$i][$attribute][0];
}
$result[$RID[1]] = $resultSet;
}
$nextStepGroupRID = $nextStepGroupRID+$searchStep;
}while($adResult['count']>1);
var_dump($result);
的$ adConn->的搜索方法是这样的:可能出现
function search($filter, $attributes = false, $base_dn = null) {
if(!isset($base_dn)){
$base_dn = $this->baseDN;
}
$entries = false;
if (is_string($filter) && $this->bind) {
if (is_array($attributes)) {
$search = ldap_search($this->resource, $base_dn, $filter, $attributes);
} else {
$search = ldap_search($this->resource, $base_dn, $filter);
}
if ($search !== false) {
$entries = ldap_get_entries($this->resource, $search);
}
}
return $entries;
}
感谢关键字'简单的分页结果'导致[此问题](http://stackoverflow.com/questions/1473075/enumerate-all-users-in-ldap-with-php),它有一个伟大的回答。似乎做到这一点的唯一方法是adoDB,好奇这是如何解决的。 – Envyrus 2011-12-27 07:23:13
你的链接不见了。 – MrUpsidown 2014-09-30 07:12:46