3 # script to call a DRS GetNCChanges from the command line
4 # this is useful for plugfest testing
7 from optparse
import OptionParser
9 sys
.path
.insert(0, "bin/python")
12 import samba
.getopt
as options
13 from samba
.dcerpc
import drsuapi
, misc
14 from samba
.samdb
import SamDB
15 from samba
.auth
import system_session
16 from samba
.ndr
import ndr_unpack
19 '''make a DsBind call, returning the binding handle'''
20 bind_info
= drsuapi
.DsBindInfoCtr()
22 bind_info
.info
= drsuapi
.DsBindInfo28()
23 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_BASE
24 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION
25 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI
26 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2
27 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS
28 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1
29 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
30 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE
31 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2
32 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION
33 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2
34 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
35 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND
36 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO
37 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
38 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01
39 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP
40 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY
41 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
42 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2
43 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6
44 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS
45 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
46 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5
47 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
48 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3
49 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7
50 bind_info
.info
.supported_extensions |
= drsuapi
.DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT
51 (info
, handle
) = drs
.DsBind(misc
.GUID(drsuapi
.DRSUAPI_DS_BIND_GUID
), bind_info
)
55 def drs_get_rodc_partial_attribute_set(samdb
):
56 '''get a list of attributes for RODC replication'''
57 partial_attribute_set
= drsuapi
.DsPartialAttributeSet()
58 partial_attribute_set
.version
= 1
62 # the exact list of attids we send is quite critical. Note that
63 # we do ask for the secret attributes, but set set SPECIAL_SECRET_PROCESSING
65 schema_dn
= samdb
.get_schema_basedn()
66 res
= samdb
.search(base
=schema_dn
, scope
=ldb
.SCOPE_SUBTREE
,
67 expression
="objectClass=attributeSchema",
68 attrs
=["lDAPDisplayName", "systemFlags",
72 ldap_display_name
= r
["lDAPDisplayName"][0]
73 if "systemFlags" in r
:
74 system_flags
= r
["systemFlags"][0]
75 if (int(system_flags
) & (samba
.dsdb
.DS_FLAG_ATTR_NOT_REPLICATED |
76 samba
.dsdb
.DS_FLAG_ATTR_IS_CONSTRUCTED
)):
78 if "searchFlags" in r
:
79 search_flags
= r
["searchFlags"][0]
80 if (int(search_flags
) & samba
.dsdb
.SEARCH_FLAG_RODC_ATTRIBUTE
):
82 attid
= samdb
.get_attid_from_lDAPDisplayName(ldap_display_name
)
83 attids
.append(int(attid
))
85 # the attids do need to be sorted, or windows doesn't return
86 # all the attributes we need
88 partial_attribute_set
.attids
= attids
89 partial_attribute_set
.num_attids
= len(attids
)
90 return partial_attribute_set
93 ########### main code ###########
94 if __name__
== "__main__":
95 parser
= OptionParser("getncchanges [options] server")
96 sambaopts
= options
.SambaOptions(parser
)
97 parser
.add_option_group(sambaopts
)
98 credopts
= options
.CredentialsOptionsDouble(parser
)
99 parser
.add_option_group(credopts
)
101 parser
.add_option("", "--dn", dest
="dn", help="DN to replicate",)
102 parser
.add_option("", "--exop", dest
="exop", help="extended operation",)
103 parser
.add_option("", "--pas", dest
="use_pas", action
='store_true', default
=False,
104 help="send partial attribute set (for RODC)")
105 parser
.add_option("", "--nb-iter", type='int', help="Number of getncchange iterations")
106 parser
.add_option("", "--dest-dsa", type='str', help="destination DSA GUID")
107 parser
.add_option("", "--rodc", action
='store_true', default
=False,
108 help='use RODC replica flags')
109 parser
.add_option("", "--partial-rw", action
='store_true', default
=False,
110 help='use RW partial replica flags, not be confused with --pas')
111 parser
.add_option("", "--replica-flags", type='int',
112 default
=drsuapi
.DRSUAPI_DRS_INIT_SYNC |
113 drsuapi
.DRSUAPI_DRS_PER_SYNC |
114 drsuapi
.DRSUAPI_DRS_WRIT_REP |
115 drsuapi
.DRSUAPI_DRS_GET_ANC |
116 drsuapi
.DRSUAPI_DRS_NEVER_SYNCED
,
117 help='replica flags')
119 (opts
, args
) = parser
.parse_args()
121 opts
.replica_flags
= drsuapi
.DRSUAPI_DRS_INIT_SYNC |\
122 drsuapi
.DRSUAPI_DRS_PER_SYNC |\
123 drsuapi
.DRSUAPI_DRS_GET_ANC |\
124 drsuapi
.DRSUAPI_DRS_NEVER_SYNCED |\
125 drsuapi
.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING |\
126 drsuapi
.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP
129 opts
.replica_flags
= drsuapi
.DRSUAPI_DRS_INIT_SYNC |\
130 drsuapi
.DRSUAPI_DRS_PER_SYNC |\
131 drsuapi
.DRSUAPI_DRS_GET_ANC |\
132 drsuapi
.DRSUAPI_DRS_NEVER_SYNCED
134 lp
= sambaopts
.get_loadparm()
135 creds
= credopts
.get_credentials(lp
)
138 parser
.error("You must supply a server")
140 if creds
.is_anonymous():
141 parser
.error("You must supply credentials")
143 if opts
.partial_rw
and opts
.rodc
:
144 parser
.error("Can't specify --partial-rw and --rodc")
148 binding_str
= "ncacn_ip_tcp:%s[seal,print]" % server
150 drs
= drsuapi
.drsuapi(binding_str
, lp
, creds
)
151 drs_handle
= do_DsBind(drs
)
152 print "DRS Handle: %s" % drs_handle
154 req8
= drsuapi
.DsGetNCChangesRequest8()
156 samdb
= SamDB(url
="ldap://%s" % server
,
157 session_info
=system_session(),
158 credentials
=creds
, lp
=lp
)
161 local_samdb
= SamDB(url
=None, session_info
=system_session(),
162 credentials
=creds
, lp
=lp
)
165 opts
.dn
= str(samdb
.get_default_basedn())
167 if opts
.exop
is None:
168 exop
= drsuapi
.DRSUAPI_EXOP_NONE
170 exop
= int(opts
.exop
)
172 dest_dsa
= opts
.dest_dsa
174 print "no dest_dsa specified trying to figure out from ldap"
175 msgs
= samdb
.search(controls
=["search_options:1:2"],
176 expression
='(objectclass=ntdsdsa)')
178 dest_dsa
= str(ndr_unpack(misc
.GUID
, msgs
[0]["invocationId"][0]))
179 print "Found this dsa: %s" % dest_dsa
184 print "Unable to find the dest_dsa automatically please specify it"
188 null_guid
= misc
.GUID()
189 req8
.destination_dsa_guid
= misc
.GUID(dest_dsa
)
190 req8
.source_dsa_invocation_id
= misc
.GUID(samdb
.get_invocation_id())
191 req8
.naming_context
= drsuapi
.DsReplicaObjectIdentifier()
192 req8
.naming_context
.dn
= opts
.dn
.decode("utf-8")
193 req8
.highwatermark
= drsuapi
.DsReplicaHighWaterMark()
194 req8
.highwatermark
.tmp_highest_usn
= 0
195 req8
.highwatermark
.reserved_usn
= 0
196 req8
.highwatermark
.highest_usn
= 0
197 req8
.uptodateness_vector
= None
198 req8
.replica_flags
= opts
.replica_flags
199 req8
.max_object_count
= 402
200 req8
.max_ndr_size
= 402116
201 req8
.extended_op
= exop
204 req8
.partial_attribute_set
= drs_get_rodc_partial_attribute_set(local_samdb
)
206 req8
.partial_attribute_set
= None
207 req8
.partial_attribute_set_ex
= None
208 req8
.mapping_ctr
.num_mappings
= 0
209 req8
.mapping_ctr
.mappings
= None
213 (level
, ctr
) = drs
.DsGetNCChanges(drs_handle
, 8, req8
)
215 if ctr
.more_data
== 0 or opts
.nb_iter
== nb_iter
:
217 req8
.highwatermark
= ctr
.new_highwatermark