Skip to content

Commit e8b652a

Browse files
committed
Add support for RFC-4533 style directory synchronization.
1 parent 52d4b1a commit e8b652a

34 files changed

+2501
-6
lines changed

src/FreeDSx/Ldap/Control/Control.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class Control implements ProtocolElementInterface, Stringable
4444

4545
public const OID_EXTENDED_DN = '1.2.840.113556.1.4.529';
4646

47+
public const OID_MANAGE_DSA_IT = '2.16.840.1.113730.3.4.2';
48+
4749
public const OID_PAGING = '1.2.840.113556.1.4.319';
4850

4951
public const OID_POLICY_HINTS = '1.2.840.113556.1.4.2239';
@@ -58,6 +60,14 @@ class Control implements ProtocolElementInterface, Stringable
5860

5961
public const OID_SHOW_RECYCLED = '1.2.840.113556.1.4.2064';
6062

63+
public const OID_SUBENTRIES = '1.3.6.1.4.1.4203.1.10.1';
64+
65+
public const OID_SYNC_REQUEST = '1.3.6.1.4.1.4203.1.9.1.1';
66+
67+
public const OID_SYNC_STATE = '1.3.6.1.4.1.4203.1.9.1.2';
68+
69+
public const OID_SYNC_DONE = '1.3.6.1.4.1.4203.1.9.1.3';
70+
6171
public const OID_SUBTREE_DELETE = '1.2.840.113556.1.4.805';
6272

6373
public const OID_SORTING = '1.2.840.113556.1.4.473';
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the FreeDSx LDAP package.
7+
*
8+
* (c) Chad Sikorra <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace FreeDSx\Ldap\Control;
15+
16+
use FreeDSx\Asn1\Asn1;
17+
use FreeDSx\Asn1\Type\AbstractType;
18+
use FreeDSx\Asn1\Type\BooleanType;
19+
use FreeDSx\Ldap\Exception\ProtocolException;
20+
21+
/**
22+
* Represents a subentries control. RFC 3672.
23+
*
24+
* @author Chad Sikorra <[email protected]>
25+
*/
26+
class SubentriesControl extends Control
27+
{
28+
private bool $isVisible;
29+
30+
/**
31+
* @param bool $isVisible
32+
*/
33+
public function __construct(bool $isVisible = true)
34+
{
35+
$this->isVisible = $isVisible;
36+
37+
parent::__construct(
38+
self::OID_SUBENTRIES,
39+
true
40+
);
41+
}
42+
43+
public function getIsVisible() : bool
44+
{
45+
return $this->isVisible;
46+
}
47+
48+
public function setIsVisible(bool $isVisible): self
49+
{
50+
$this->isVisible = $isVisible;
51+
52+
return $this;
53+
}
54+
55+
/**
56+
* {@inheritDoc}
57+
*/
58+
public function toAsn1(): AbstractType
59+
{
60+
$this->controlValue = Asn1::boolean($this->isVisible);
61+
62+
return parent::toAsn1();
63+
}
64+
65+
/**
66+
* {@inheritDoc}
67+
*/
68+
public static function fromAsn1(AbstractType $type): static
69+
{
70+
$isVisible = self::decodeEncodedValue($type);
71+
if (!$isVisible instanceof BooleanType) {
72+
throw new ProtocolException('Expected a boolean type for a subentries control value.');
73+
}
74+
75+
return self::mergeControlData(
76+
new static($isVisible->getValue()),
77+
$type
78+
);
79+
}
80+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the FreeDSx LDAP package.
7+
*
8+
* (c) Chad Sikorra <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace FreeDSx\Ldap\Control\Sync;
15+
16+
use FreeDSx\Asn1\Asn1;
17+
use FreeDSx\Asn1\Type\AbstractType;
18+
use FreeDSx\Asn1\Type\BooleanType;
19+
use FreeDSx\Asn1\Type\OctetStringType;
20+
use FreeDSx\Asn1\Type\SequenceType;
21+
use FreeDSx\Ldap\Control\Control;
22+
use FreeDSx\Ldap\Exception\ProtocolException;
23+
use function count;
24+
25+
/**
26+
* Represents a syncStateValue control. RFC 4533.
27+
*
28+
* syncDoneValue ::= SEQUENCE {
29+
* cookie syncCookie OPTIONAL,
30+
* refreshDeletes BOOLEAN DEFAULT FALSE
31+
* }
32+
*
33+
* @author Chad Sikorra <[email protected]
34+
* @see https://tools.ietf.org/html/rfc4533
35+
*/
36+
class SyncDoneControl extends Control
37+
{
38+
private ?string $cookie;
39+
40+
private bool $refreshDeletes;
41+
42+
public function __construct(
43+
?string $cookie = null,
44+
bool $refreshDeletes = false,
45+
) {
46+
$this->cookie = $cookie;
47+
$this->refreshDeletes = $refreshDeletes;
48+
49+
parent::__construct(
50+
self::OID_SYNC_DONE,
51+
true
52+
);
53+
}
54+
55+
public function getCookie(): ?string
56+
{
57+
return $this->cookie;
58+
}
59+
60+
public function setCookie(?string $cookie): self
61+
{
62+
$this->cookie = $cookie;
63+
64+
return $this;
65+
}
66+
67+
public function getRefreshDeletes(): bool
68+
{
69+
return $this->refreshDeletes;
70+
}
71+
72+
public function setRefreshDeletes(bool $refreshDeletes): self
73+
{
74+
$this->refreshDeletes = $refreshDeletes;
75+
76+
return $this;
77+
}
78+
79+
/**
80+
* {@inheritdoc}
81+
*/
82+
public function toAsn1(): AbstractType
83+
{
84+
$this->controlValue = Asn1::sequence();
85+
if ($this->cookie !== null) {
86+
$this->controlValue->addChild(Asn1::octetString(
87+
$this->cookie
88+
));
89+
}
90+
$this->controlValue->addChild(Asn1::boolean(
91+
$this->refreshDeletes ?? false
92+
));
93+
94+
return parent::toAsn1();
95+
}
96+
97+
/**
98+
* {@inheritdoc}
99+
*/
100+
public static function fromAsn1(AbstractType $type): static
101+
{
102+
$sync = self::decodeEncodedValue($type);
103+
if (!$sync instanceof SequenceType || count($sync->getChildren()) > 2) {
104+
throw new ProtocolException(
105+
'Expected a sequence type with 2 or less values for a sync done control value.'
106+
);
107+
}
108+
109+
$cookie = null;
110+
$refreshDeletes = false;
111+
foreach ($sync->getChildren() as $child) {
112+
if ($child instanceof OctetStringType) {
113+
$cookie = $child->getValue();
114+
} elseif ($child instanceof BooleanType) {
115+
$refreshDeletes = $child->getValue();
116+
}
117+
}
118+
119+
return self::mergeControlData(
120+
new static(
121+
$cookie,
122+
$refreshDeletes
123+
),
124+
$type
125+
);
126+
}
127+
}

0 commit comments

Comments
 (0)