/** * 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; }