function it_should_parse_a_SDDL_string_that_represents_the_default_exchange_mailbox_permissions() { $exchHex = '010004801400000020000000000000002c00000001010000000000050a00000001010000000000050a00000004001c0001000000000214000100020001010000000000050a000000'; $exchSddl = 'O:PSG:PSD:(A;CI;RCCC;;;PS)'; $this->parse($exchSddl)->toBinary()->shouldBeEqualTo(hex2bin($exchHex)); $sd = (new SecurityDescriptor())->setOwner(new SID('PS'))->setGroup(new SID('PS')); $acl = new Dacl(); $ace = (new Ace(new AceType('A')))->setFlags((new AceFlags())->add(AceFlags::SHORT_NAME['CI']))->setRights((new AceRights())->add(AceRights::SHORT_NAME['RC'])->add(AceRights::SHORT_NAME['CC']))->setTrustee(new SID('PS')); $acl->addAce($ace); $sd->setDacl($acl); $this->parse($exchSddl)->toBinary()->shouldBeEqualTo($sd->toBinary()); }
/** * 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; }