1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
#!/usr/bin/python
import optparse
import sys
import base64
sys.path.insert(0, "bin/python")
import samba.getopt as options
from samba.dcerpc import drsblobs, misc
from samba.ndr import ndr_pack, ndr_unpack
from samba import Ldb
parser = optparse.OptionParser("demodirsync [options]")
sambaopts = options.SambaOptions(parser)
credopts = options.CredentialsOptions(parser)
parser.add_option_group(credopts)
parser.add_option("-b", type="string", metavar="BASE",
help="set base DN for the search")
parser.add_option("--host", type="string", metavar="HOST",
help="Ip of the host")
lp = sambaopts.get_loadparm()
creds = credopts.get_credentials(lp)
opts = parser.parse_args()[0]
if opts.host is None:
print("Usage: demodirsync.py --host HOST [-b BASE]")
sys.exit(1)
def printdirsync(ctl):
arr = ctl.split(':')
if arr[0] == 'dirsync':
print("Need to continue: %s" % arr[1])
cookie = ndr_unpack(drsblobs.ldapControlDirSyncCookie, base64.b64decode(arr[3]))
print("DC's NTDS guid: %s " % cookie.blob.guid1)
print("highest usn %s" % cookie.blob.highwatermark.highest_usn)
print("tmp highest usn %s" % cookie.blob.highwatermark.tmp_highest_usn)
print("reserved usn %s" % cookie.blob.highwatermark.reserved_usn)
if cookie.blob.extra_length > 0:
print("highest usn in extra %s" % cookie.blob.extra.ctr.cursors[0].highest_usn)
return cookie
remote_ldb = Ldb("ldap://" + opts.host + ":389", credentials=creds, lp=lp)
tab = []
if opts.b:
base = opts.b
else:
base = None
guid = None
(msgs, ctrls) = remote_ldb.search(expression="(samaccountname=administrator)", base=base, attrs=["objectClass"], controls=["dirsync:1:1:50"])
if (len(ctrls)):
for ctl in ctrls:
arr = ctl.split(':')
if arr[0] == 'dirsync':
cookie = ndr_unpack(drsblobs.ldapControlDirSyncCookie, base64.b64decode(arr[3]))
guid = cookie.blob.guid1
if not guid:
print("No dirsync control ... strange")
sys.exit(1)
print("")
print("Getting first guest without any cookie")
(msgs, ctrls) = remote_ldb.searchex(expression="(samaccountname=guest)", base=base, attrs=["objectClass"], controls=["dirsync:1:1:50"])
cookie = None
if (len(ctrls)):
for ctl in ctrls:
cookie = printdirsync(ctl)
print("Returned %d entries" % len(msgs))
savedcookie = cookie
print("")
print("Getting allusers with cookie")
controls = ["dirsync:1:1:50:%s" % base64.b64encode(ndr_pack(cookie)).decode('utf8')]
(msgs, ctrls) = remote_ldb.searchex(expression="(samaccountname=*)", base=base, attrs=["objectClass"], controls=controls)
if (len(ctrls)):
for ctl in ctrls:
printdirsync(ctl)
print("Returned %d entries" % len(msgs))
cookie = savedcookie
cookie.blob.guid1 = misc.GUID("128a99bf-e2df-4832-ac0a-1fb625e530db")
if cookie.blob.extra_length > 0:
cookie.blob.extra.ctr.cursors[0].source_dsa_invocation_id = misc.GUID("128a99bf-e2df-4832-ac0a-1fb625e530db")
print("")
print("Getting all the entries")
controls = ["dirsync:1:1:50:%s" % base64.b64encode(ndr_pack(cookie)).decode('utf8')]
(msgs, ctrls) = remote_ldb.searchex(expression="(objectclass=*)", base=base, controls=controls)
cont = 0
if (len(ctrls)):
for ctl in ctrls:
cookie = printdirsync(ctl)
if cookie is not None:
cont = (ctl.split(':'))[1]
print("Returned %d entries" % len(msgs))
usn = cookie.blob.highwatermark.tmp_highest_usn
if cookie.blob.extra_length > 0:
bigusn = cookie.blob.extra.ctr.cursors[0].highest_usn
else:
bigusn = usn + 1000
while (cont == "1"):
print("")
controls = ["dirsync:1:1:50:%s" % base64.b64encode(ndr_pack(cookie)).decode('utf8')]
(msgs, ctrls) = remote_ldb.searchex(expression="(objectclass=*)", base=base, controls=controls)
if (len(ctrls)):
for ctl in ctrls:
cookie = printdirsync(ctl)
if cookie is not None:
cont = (ctl.split(':'))[1]
print("Returned %d entries" % len(msgs))
print("")
print("Getting with cookie but usn changed to %d we should use the one in extra" % (bigusn - 1))
cookie.blob.highwatermark.highest_usn = 0
cookie.blob.highwatermark.tmp_highest_usn = usn - 2
if cookie.blob.extra_length > 0:
print("here")
cookie.blob.extra.ctr.cursors[0].highest_usn = bigusn - 1
controls = ["dirsync:1:1:50:%s" % base64.b64encode(ndr_pack(cookie)).decode('utf8')]
(msgs, ctrls) = remote_ldb.searchex(expression="(objectclass=*)", base=base, controls=controls)
if (len(ctrls)):
for ctl in ctrls:
cookie = printdirsync(ctl)
print("Returned %d entries" % len(msgs))
print("")
print("Getting with cookie but usn %d changed and extra/cursor GUID too" % (usn - 2))
print(" so that it's (tmp)highest_usn that drives the limit")
cookie.blob.highwatermark.highest_usn = 0
cookie.blob.highwatermark.tmp_highest_usn = usn - 2
if cookie.blob.extra_length > 0:
cookie.blob.extra.ctr.cursors[0].source_dsa_invocation_id = misc.GUID("128a99bf-e2df-4832-ac0a-1fb625e530db")
cookie.blob.extra.ctr.cursors[0].highest_usn = bigusn - 1
controls = ["dirsync:1:1:50:%s" % base64.b64encode(ndr_pack(cookie)).decode('utf8')]
(msgs, ctrls) = remote_ldb.searchex(expression="(objectclass=*)", base=base, controls=controls)
if (len(ctrls)):
for ctl in ctrls:
cookie = printdirsync(ctl)
print("Returned %d entries" % len(msgs))
print("")
print("Getting with cookie but usn changed to %d" % (usn - 2))
cookie.blob.highwatermark.highest_usn = 0
cookie.blob.highwatermark.tmp_highest_usn = (usn - 2)
if cookie.blob.extra_length > 0:
cookie.blob.extra.ctr.cursors[0].highest_usn = (usn - 2)
controls = ["dirsync:1:1:50:%s" % base64.b64encode(ndr_pack(cookie)).decode('utf8')]
(msgs, ctrls) = remote_ldb.searchex(expression="(objectclass=*)", base=base, controls=controls)
if (len(ctrls)):
for ctl in ctrls:
cookie = printdirsync(ctl)
print("Returned %d entries" % len(msgs))
|