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
|
#!/usr/bin/env python3
# script to call a DRS GetNCChanges from the command line
# this is useful for plugfest testing
import sys
from optparse import OptionParser
sys.path.insert(0, "bin/python")
import samba, ldb
import samba.getopt as options
from samba.dcerpc import drsuapi, misc
from samba.samdb import SamDB
from samba.auth import system_session
from samba.ndr import ndr_unpack
from samba.drs_utils import drs_get_rodc_partial_attribute_set, drs_DsBind
########### main code ###########
if __name__ == "__main__":
parser = OptionParser("getncchanges [options] server")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(sambaopts)
credopts = options.CredentialsOptionsDouble(parser)
parser.add_option_group(credopts)
parser.add_option("", "--dn", dest="dn", help="DN to replicate",)
parser.add_option("", "--exop", dest="exop", help="extended operation",)
parser.add_option("", "--pas", dest="use_pas", action='store_true', default=False,
help="send partial attribute set (for RODC)")
parser.add_option("", "--nb-iter", type='int', help="Number of getncchange iterations")
parser.add_option("", "--dest-dsa", type='str', help="destination DSA GUID")
parser.add_option("", "--rodc", action='store_true', default=False,
help='use RODC replica flags')
parser.add_option("", "--partial-rw", action='store_true', default=False,
help='use RW partial replica flags, not be confused with --pas')
parser.add_option("", "--replica-flags", type='int',
default=drsuapi.DRSUAPI_DRS_INIT_SYNC |
drsuapi.DRSUAPI_DRS_PER_SYNC |
drsuapi.DRSUAPI_DRS_WRIT_REP |
drsuapi.DRSUAPI_DRS_GET_ANC |
drsuapi.DRSUAPI_DRS_NEVER_SYNCED,
help='replica flags')
(opts, args) = parser.parse_args()
if opts.rodc:
opts.replica_flags = drsuapi.DRSUAPI_DRS_INIT_SYNC |\
drsuapi.DRSUAPI_DRS_PER_SYNC |\
drsuapi.DRSUAPI_DRS_GET_ANC |\
drsuapi.DRSUAPI_DRS_NEVER_SYNCED |\
drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING |\
drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP
if opts.partial_rw:
opts.replica_flags = drsuapi.DRSUAPI_DRS_INIT_SYNC |\
drsuapi.DRSUAPI_DRS_PER_SYNC |\
drsuapi.DRSUAPI_DRS_GET_ANC |\
drsuapi.DRSUAPI_DRS_NEVER_SYNCED
lp = sambaopts.get_loadparm()
creds = credopts.get_credentials(lp)
if len(args) != 1:
parser.error("You must supply a server")
if creds.is_anonymous():
parser.error("You must supply credentials")
if opts.partial_rw and opts.rodc:
parser.error("Can't specify --partial-rw and --rodc")
server = args[0]
binding_str = "ncacn_ip_tcp:%s[seal,print]" % server
drs = drsuapi.drsuapi(binding_str, lp, creds)
drs_handle, supported_extensions = drs_DsBind(drs)
print("DRS Handle: %s" % drs_handle)
req8 = drsuapi.DsGetNCChangesRequest8()
samdb = SamDB(url="ldap://%s" % server,
session_info=system_session(),
credentials=creds, lp=lp)
if opts.use_pas:
local_samdb = SamDB(url=None, session_info=system_session(),
credentials=creds, lp=lp)
if opts.dn is None:
opts.dn = str(samdb.get_default_basedn())
if opts.exop is None:
exop = drsuapi.DRSUAPI_EXOP_NONE
else:
exop = int(opts.exop)
dest_dsa = opts.dest_dsa
if not dest_dsa:
print("no dest_dsa specified trying to figure out from ldap")
msgs = samdb.search(controls=["search_options:1:2"],
expression='(objectclass=ntdsdsa)')
if len(msgs) == 1:
dest_dsa = str(ndr_unpack(misc.GUID, msgs[0]["invocationId"][0]))
print("Found this dsa: %s" % dest_dsa)
else:
# TODO fixme
pass
if not dest_dsa:
print("Unable to find the dest_dsa automatically please specify it")
import sys
sys.exit(1)
null_guid = misc.GUID()
req8.destination_dsa_guid = misc.GUID(dest_dsa)
req8.source_dsa_invocation_id = misc.GUID(samdb.get_invocation_id())
req8.naming_context = drsuapi.DsReplicaObjectIdentifier()
req8.naming_context.dn = opts.dn.decode("utf-8")
req8.highwatermark = drsuapi.DsReplicaHighWaterMark()
req8.highwatermark.tmp_highest_usn = 0
req8.highwatermark.reserved_usn = 0
req8.highwatermark.highest_usn = 0
req8.uptodateness_vector = None
req8.replica_flags = opts.replica_flags
req8.max_object_count = 402
req8.max_ndr_size = 402116
req8.extended_op = exop
req8.fsmo_info = 0
if opts.use_pas:
req8.partial_attribute_set = drs_get_rodc_partial_attribute_set(local_samdb)
else:
req8.partial_attribute_set = None
req8.partial_attribute_set_ex = None
req8.mapping_ctr.num_mappings = 0
req8.mapping_ctr.mappings = None
nb_iter = 0
while True:
(level, ctr) = drs.DsGetNCChanges(drs_handle, 8, req8)
nb_iter += 1
if ctr.more_data == 0 or opts.nb_iter == nb_iter:
break
req8.highwatermark = ctr.new_highwatermark
|