/**
* Get the binary string form of the security descriptor.
*
* @param bool $canonicalize Whether or not to canonicalize the DACL
* @return string
*/
public function toBinary($canonicalize = true)
{
$offsetOwner = 0;
$offsetGroup = 0;
$offsetDacl = 0;
$offsetSacl = 0;
$owner = $this->owner ? $this->owner->toBinary() : null;
$group = $this->group ? $this->group->toBinary() : null;
$dacl = $this->dacl ? $this->dacl->toBinary($canonicalize) : null;
$sacl = $this->sacl ? $this->sacl->toBinary() : null;
if ($owner === null || $group === null) {
throw new LogicException('The owner and the group must be set in the Security Descriptor.');
}
if ($sacl === null && $dacl === null) {
throw new LogicException('Either the SACL or DACL must be set on the Security Descriptor.');
}
/**
* According the the MS docs, the order of the elements is not important. And indeed, I have found no rhyme or
* reason as to how the owner/group/sacl/dacl elements are ordered in the security descriptor. As long as they
* point to the correct offset where the element is located then it will work. But the order seems unpredictable
* as far as coming from AD/Exchange/etc.
*/
$offset = 40;
if ($owner) {
$offsetOwner = $offset;
$offset += strlen(bin2hex($owner));
}
if ($group) {
$offsetGroup = $offset;
$offset += strlen(bin2hex($group));
}
if ($sacl) {
$offsetSacl = $offset;
$offset += strlen(bin2hex($sacl));
}
if ($dacl) {
$offsetDacl = $offset;
}
return pack('C1C1v1V1V1V1V1', $this->revision, $this->rmControlFlags->getValue(), $this->controlFlags->getValue(), $offsetOwner / 2, $offsetGroup / 2, $offsetSacl / 2, $offsetDacl / 2) . $owner . $group . $sacl . $dacl;
}