1 # domain management - domain trust
3 # Copyright Matthias Dieter Wallnoefer 2009
4 # Copyright Andrew Kroeger 2009
5 # Copyright Jelmer Vernooij 2007-2012
6 # Copyright Giampaolo Lauria 2011
7 # Copyright Matthieu Patou <mat@matws.net> 2011
8 # Copyright Andrew Bartlett 2008-2015
9 # Copyright Stefan Metzmacher 2012
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 from getpass
import getpass
29 import samba
.getopt
as options
31 from samba
import NTSTATUSError
, ntstatus
, werror
32 from samba
.auth
import system_session
33 from samba
.dcerpc
import drsblobs
, lsa
, nbt
, netlogon
, security
34 from samba
.net
import Net
35 from samba
.netcmd
import Command
, CommandError
, Option
, SuperCommand
36 from samba
.samdb
import SamDB
37 from samba
.lsa_utils
import OpenPolicyFallback
, CreateTrustedDomainFallback
40 class LocalDCCredentialsOptions(options
.CredentialsOptions
):
41 def __init__(self
, parser
):
42 options
.CredentialsOptions
.__init
__(self
, parser
, special_name
="local-dc")
45 class DomainTrustCommand(Command
):
46 """List domain trusts."""
49 Command
.__init
__(self
)
52 self
.local_server
= None
53 self
.local_binding_string
= None
54 self
.local_creds
= None
56 self
.remote_server
= None
57 self
.remote_binding_string
= None
58 self
.remote_creds
= None
61 return ctypes
.c_uint32(v
).value
63 def check_runtime_error(self
, runtime
, val
):
67 err32
= self
._uint
32(runtime
.args
[0])
73 class LocalRuntimeError(CommandError
):
74 def __init__(exception_self
, self
, runtime
, message
):
75 err32
= self
._uint
32(runtime
.args
[0])
76 errstr
= runtime
.args
[1]
77 msg
= "LOCAL_DC[%s]: %s - ERROR(0x%08X) - %s" % (
78 self
.local_server
, message
, err32
, errstr
)
79 CommandError
.__init
__(exception_self
, msg
)
81 class RemoteRuntimeError(CommandError
):
82 def __init__(exception_self
, self
, runtime
, message
):
83 err32
= self
._uint
32(runtime
.args
[0])
84 errstr
= runtime
.args
[1]
85 msg
= "REMOTE_DC[%s]: %s - ERROR(0x%08X) - %s" % (
86 self
.remote_server
, message
, err32
, errstr
)
87 CommandError
.__init
__(exception_self
, msg
)
89 class LocalLdbError(CommandError
):
90 def __init__(exception_self
, self
, ldb_error
, message
):
91 errval
= ldb_error
.args
[0]
92 errstr
= ldb_error
.args
[1]
93 msg
= "LOCAL_DC[%s]: %s - ERROR(%d) - %s" % (
94 self
.local_server
, message
, errval
, errstr
)
95 CommandError
.__init
__(exception_self
, msg
)
97 def setup_local_server(self
, sambaopts
, localdcopts
):
98 if self
.local_server
is not None:
99 return self
.local_server
101 lp
= sambaopts
.get_loadparm()
103 local_server
= localdcopts
.ipaddress
104 if local_server
is None:
105 server_role
= lp
.server_role()
106 if server_role
!= "ROLE_ACTIVE_DIRECTORY_DC":
107 raise CommandError("Invalid server_role %s" % (server_role
))
108 local_server
= lp
.get('netbios name')
109 local_transport
= "ncalrpc"
110 local_binding_options
= ""
111 local_binding_options
+= ",auth_type=ncalrpc_as_system"
112 local_ldap_url
= None
115 local_transport
= "ncacn_np"
116 local_binding_options
= ""
117 local_ldap_url
= "ldap://%s" % local_server
118 local_creds
= localdcopts
.get_credentials(lp
)
122 self
.local_server
= local_server
123 self
.local_binding_string
= "%s:%s[%s]" % (local_transport
, local_server
, local_binding_options
)
124 self
.local_ldap_url
= local_ldap_url
125 self
.local_creds
= local_creds
126 return self
.local_server
128 def new_local_lsa_connection(self
):
129 return lsa
.lsarpc(self
.local_binding_string
, self
.local_lp
, self
.local_creds
)
131 def new_local_netlogon_connection(self
):
132 return netlogon
.netlogon(self
.local_binding_string
, self
.local_lp
, self
.local_creds
)
134 def new_local_ldap_connection(self
):
135 return SamDB(url
=self
.local_ldap_url
,
136 session_info
=system_session(),
137 credentials
=self
.local_creds
,
140 def setup_remote_server(self
, credopts
, domain
,
142 require_writable
=True):
145 assert require_writable
147 if self
.remote_server
is not None:
148 return self
.remote_server
150 self
.remote_server
= "__unknown__remote_server__.%s" % domain
151 assert self
.local_server
is not None
153 remote_creds
= credopts
.get_credentials(self
.local_lp
)
154 remote_server
= credopts
.ipaddress
155 remote_binding_options
= ""
157 # TODO: we should also support NT4 domains
158 # we could use local_netlogon.netr_DsRGetDCNameEx2() with the remote domain name
159 # and delegate NBT or CLDAP to the local netlogon server
161 remote_net
= Net(remote_creds
, self
.local_lp
, server
=remote_server
)
162 remote_flags
= nbt
.NBT_SERVER_LDAP | nbt
.NBT_SERVER_DS
164 remote_flags |
= nbt
.NBT_SERVER_WRITABLE
166 remote_flags |
= nbt
.NBT_SERVER_PDC
167 remote_info
= remote_net
.finddc(flags
=remote_flags
, domain
=domain
, address
=remote_server
)
168 except NTSTATUSError
as error
:
169 raise CommandError("Failed to find a writeable DC for domain '%s': %s" %
170 (domain
, error
.args
[1]))
172 raise CommandError("Failed to find a writeable DC for domain '%s'" % domain
)
174 nbt
.NBT_SERVER_PDC
: "PDC",
175 nbt
.NBT_SERVER_GC
: "GC",
176 nbt
.NBT_SERVER_LDAP
: "LDAP",
177 nbt
.NBT_SERVER_DS
: "DS",
178 nbt
.NBT_SERVER_KDC
: "KDC",
179 nbt
.NBT_SERVER_TIMESERV
: "TIMESERV",
180 nbt
.NBT_SERVER_CLOSEST
: "CLOSEST",
181 nbt
.NBT_SERVER_WRITABLE
: "WRITABLE",
182 nbt
.NBT_SERVER_GOOD_TIMESERV
: "GOOD_TIMESERV",
183 nbt
.NBT_SERVER_NDNC
: "NDNC",
184 nbt
.NBT_SERVER_SELECT_SECRET_DOMAIN_6
: "SELECT_SECRET_DOMAIN_6",
185 nbt
.NBT_SERVER_FULL_SECRET_DOMAIN_6
: "FULL_SECRET_DOMAIN_6",
186 nbt
.NBT_SERVER_ADS_WEB_SERVICE
: "ADS_WEB_SERVICE",
187 nbt
.NBT_SERVER_DS_8
: "DS_8",
188 nbt
.NBT_SERVER_DS_9
: "DS_9",
189 nbt
.NBT_SERVER_DS_10
: "DS_10",
190 nbt
.NBT_SERVER_HAS_DNS_NAME
: "HAS_DNS_NAME",
191 nbt
.NBT_SERVER_IS_DEFAULT_NC
: "IS_DEFAULT_NC",
192 nbt
.NBT_SERVER_FOREST_ROOT
: "FOREST_ROOT",
194 server_type_string
= self
.generic_bitmap_to_string(flag_map
,
195 remote_info
.server_type
, names_only
=True)
196 self
.outf
.write("RemoteDC Netbios[%s] DNS[%s] ServerType[%s]\n" % (
197 remote_info
.pdc_name
,
198 remote_info
.pdc_dns_name
,
201 self
.remote_server
= remote_info
.pdc_dns_name
202 self
.remote_binding_string
= "ncacn_np:%s[%s]" % (self
.remote_server
, remote_binding_options
)
203 self
.remote_creds
= remote_creds
204 return self
.remote_server
206 def new_remote_lsa_connection(self
):
207 return lsa
.lsarpc(self
.remote_binding_string
, self
.local_lp
, self
.remote_creds
)
209 def new_remote_netlogon_connection(self
):
210 return netlogon
.netlogon(self
.remote_binding_string
, self
.local_lp
, self
.remote_creds
)
212 def get_lsa_info(self
, conn
, policy_access
):
214 in_revision_info1
= lsa
.revision_info1()
215 in_revision_info1
.revision
= 1
216 in_revision_info1
.supported_features
= (
217 lsa
.LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER
220 out_version
, out_revision_info1
, policy
= OpenPolicyFallback(
228 info
= conn
.QueryInfoPolicy2(policy
, lsa
.LSA_POLICY_INFO_DNS
)
230 return (policy
, out_version
, out_revision_info1
, info
)
232 def get_netlogon_dc_unc(self
, conn
, server
, domain
):
234 info
= conn
.netr_DsRGetDCNameEx2(server
,
235 None, 0, None, None, None,
236 netlogon
.DS_RETURN_DNS_NAME
)
239 return conn
.netr_GetDcName(server
, domain
)
241 def get_netlogon_dc_info(self
, conn
, server
):
242 info
= conn
.netr_DsRGetDCNameEx2(server
,
243 None, 0, None, None, None,
244 netlogon
.DS_RETURN_DNS_NAME
)
247 def netr_DomainTrust_to_name(self
, t
):
248 if t
.trust_type
== lsa
.LSA_TRUST_TYPE_DOWNLEVEL
:
249 return t
.netbios_name
253 def netr_DomainTrust_to_type(self
, a
, t
):
255 primary_parent
= None
257 if _t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_PRIMARY
:
259 if not _t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_TREEROOT
:
260 primary_parent
= a
[_t
.parent_index
]
263 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_IN_FOREST
:
264 if t
is primary_parent
:
267 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_TREEROOT
:
270 parent
= a
[t
.parent_index
]
271 if parent
is primary
:
276 if t
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
:
281 def netr_DomainTrust_to_transitive(self
, t
):
282 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_IN_FOREST
:
285 if t
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
:
288 if t
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
:
293 def netr_DomainTrust_to_direction(self
, t
):
294 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_INBOUND
and \
295 t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_OUTBOUND
:
298 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_INBOUND
:
301 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_OUTBOUND
:
306 def generic_enum_to_string(self
, e_dict
, v
, names_only
=False):
310 v32
= self
._uint
32(v
)
311 w
= "__unknown__%08X__" % v32
313 r
= "0x%x (%s)" % (v
, w
)
316 def generic_bitmap_to_string(self
, b_dict
, v
, names_only
=False):
321 for b
in sorted(b_dict
.keys()):
328 c32
= self
._uint
32(c
)
329 s
+= ["__unknown_%08X__" % c32
]
334 r
= "0x%x (%s)" % (v
, w
)
337 def trustType_string(self
, v
):
339 lsa
.LSA_TRUST_TYPE_DOWNLEVEL
: "DOWNLEVEL",
340 lsa
.LSA_TRUST_TYPE_UPLEVEL
: "UPLEVEL",
341 lsa
.LSA_TRUST_TYPE_MIT
: "MIT",
342 lsa
.LSA_TRUST_TYPE_DCE
: "DCE",
344 return self
.generic_enum_to_string(types
, v
)
346 def trustDirection_string(self
, v
):
348 lsa
.LSA_TRUST_DIRECTION_INBOUND |
349 lsa
.LSA_TRUST_DIRECTION_OUTBOUND
: "BOTH",
350 lsa
.LSA_TRUST_DIRECTION_INBOUND
: "INBOUND",
351 lsa
.LSA_TRUST_DIRECTION_OUTBOUND
: "OUTBOUND",
353 return self
.generic_enum_to_string(directions
, v
)
355 def trustAttributes_string(self
, v
):
357 lsa
.LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
: "NON_TRANSITIVE",
358 lsa
.LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY
: "UPLEVEL_ONLY",
359 lsa
.LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
: "QUARANTINED_DOMAIN",
360 lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
: "FOREST_TRANSITIVE",
361 lsa
.LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION
: "CROSS_ORGANIZATION",
362 lsa
.LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
: "WITHIN_FOREST",
363 lsa
.LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
: "TREAT_AS_EXTERNAL",
364 lsa
.LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION
: "USES_RC4_ENCRYPTION",
366 return self
.generic_bitmap_to_string(attributes
, v
)
368 def kerb_EncTypes_string(self
, v
):
370 security
.KERB_ENCTYPE_DES_CBC_CRC
: "DES_CBC_CRC",
371 security
.KERB_ENCTYPE_DES_CBC_MD5
: "DES_CBC_MD5",
372 security
.KERB_ENCTYPE_RC4_HMAC_MD5
: "RC4_HMAC_MD5",
373 security
.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96
: "AES128_CTS_HMAC_SHA1_96",
374 security
.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96
: "AES256_CTS_HMAC_SHA1_96",
375 security
.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96_SK
: "AES256_CTS_HMAC_SHA1_96-SK",
376 security
.KERB_ENCTYPE_FAST_SUPPORTED
: "FAST_SUPPORTED",
377 security
.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED
: "COMPOUND_IDENTITY_SUPPORTED",
378 security
.KERB_ENCTYPE_CLAIMS_SUPPORTED
: "CLAIMS_SUPPORTED",
379 security
.KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
: "RESOURCE_SID_COMPRESSION_DISABLED",
381 return self
.generic_bitmap_to_string(enctypes
, v
)
383 def entry_tln_status(self
, e_flags
, ):
385 return "Status[Enabled]"
388 lsa
.LSA_TLN_DISABLED_NEW
: "Disabled-New",
389 lsa
.LSA_TLN_DISABLED_ADMIN
: "Disabled",
390 lsa
.LSA_TLN_DISABLED_CONFLICT
: "Disabled-Conflicting",
392 return "Status[%s]" % self
.generic_bitmap_to_string(flags
, e_flags
, names_only
=True)
394 def entry_dom_status(self
, e_flags
):
396 return "Status[Enabled]"
399 lsa
.LSA_SID_DISABLED_ADMIN
: "Disabled-SID",
400 lsa
.LSA_SID_DISABLED_CONFLICT
: "Disabled-SID-Conflicting",
401 lsa
.LSA_NB_DISABLED_ADMIN
: "Disabled-NB",
402 lsa
.LSA_NB_DISABLED_CONFLICT
: "Disabled-NB-Conflicting",
404 return "Status[%s]" % self
.generic_bitmap_to_string(flags
, e_flags
, names_only
=True)
406 def write_forest_trust_info(self
, fti
, tln
=None, collisions
=None):
408 tln_string
= " TDO[%s]" % tln
412 self
.outf
.write("Namespaces[%d]%s:\n" % (
413 len(fti
.entries
), tln_string
))
415 for i
, e
in enumerate(fti
.entries
):
418 collision_string
= ""
420 if collisions
is not None:
421 for c
in collisions
.entries
:
425 collision_string
= " Collision[%s]" % (c
.name
.string
)
427 d
= e
.forest_trust_data
428 if e
.type == lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
429 self
.outf
.write("TLN: %-32s DNS[*.%s]%s\n" % (
430 self
.entry_tln_status(flags
),
431 d
.string
, collision_string
))
432 elif e
.type == lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
433 self
.outf
.write("TLN_EX: %-29s DNS[*.%s]\n" % (
435 elif e
.type == lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
:
436 self
.outf
.write("DOM: %-32s DNS[%s] Netbios[%s] SID[%s]%s\n" % (
437 self
.entry_dom_status(flags
),
438 d
.dns_domain_name
.string
,
439 d
.netbios_domain_name
.string
,
440 d
.domain_sid
, collision_string
))
444 class cmd_domain_trust_list(DomainTrustCommand
):
445 """List domain trusts."""
447 synopsis
= "%prog [options]"
449 takes_optiongroups
= {
450 "sambaopts": options
.SambaOptions
,
451 "versionopts": options
.VersionOptions
,
452 "localdcopts": LocalDCCredentialsOptions
,
458 def run(self
, sambaopts
=None, versionopts
=None, localdcopts
=None):
460 local_server
= self
.setup_local_server(sambaopts
, localdcopts
)
462 local_netlogon
= self
.new_local_netlogon_connection()
463 except RuntimeError as error
:
464 raise self
.LocalRuntimeError(self
, error
, "failed to connect netlogon server")
467 local_netlogon_trusts
= \
468 local_netlogon
.netr_DsrEnumerateDomainTrusts(local_server
,
469 netlogon
.NETR_TRUST_FLAG_IN_FOREST |
470 netlogon
.NETR_TRUST_FLAG_OUTBOUND |
471 netlogon
.NETR_TRUST_FLAG_INBOUND
)
472 except RuntimeError as error
:
473 if self
.check_runtime_error(error
, werror
.WERR_RPC_S_PROCNUM_OUT_OF_RANGE
):
474 # TODO: we could implement a fallback to lsa.EnumTrustDom()
475 raise CommandError("LOCAL_DC[%s]: netr_DsrEnumerateDomainTrusts not supported." % (
477 raise self
.LocalRuntimeError(self
, error
, "netr_DsrEnumerateDomainTrusts failed")
479 a
= local_netlogon_trusts
.array
481 if t
.trust_flags
& netlogon
.NETR_TRUST_FLAG_PRIMARY
:
483 self
.outf
.write("%-14s %-15s %-19s %s\n" % (
484 "Type[%s]" % self
.netr_DomainTrust_to_type(a
, t
),
485 "Transitive[%s]" % self
.netr_DomainTrust_to_transitive(t
),
486 "Direction[%s]" % self
.netr_DomainTrust_to_direction(t
),
487 "Name[%s]" % self
.netr_DomainTrust_to_name(t
)))
491 class cmd_domain_trust_show(DomainTrustCommand
):
492 """Show trusted domain details."""
494 synopsis
= "%prog NAME [options]"
496 takes_optiongroups
= {
497 "sambaopts": options
.SambaOptions
,
498 "versionopts": options
.VersionOptions
,
499 "localdcopts": LocalDCCredentialsOptions
,
505 takes_args
= ["domain"]
507 def run(self
, domain
, sambaopts
=None, versionopts
=None, localdcopts
=None):
509 self
.setup_local_server(sambaopts
, localdcopts
)
511 local_lsa
= self
.new_local_lsa_connection()
512 except RuntimeError as error
:
513 raise self
.LocalRuntimeError(self
, error
, "failed to connect lsa server")
516 local_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
520 local_revision_info1
,
522 ) = self
.get_lsa_info(local_lsa
, local_policy_access
)
523 except RuntimeError as error
:
524 raise self
.LocalRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
526 self
.outf
.write("LocalDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
527 local_lsa_info
.name
.string
,
528 local_lsa_info
.dns_domain
.string
,
531 lsaString
= lsa
.String()
532 lsaString
.string
= domain
535 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
537 lsa
.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
)
538 local_tdo_info
= local_tdo_full
.info_ex
539 local_tdo_posix
= local_tdo_full
.posix_offset
540 except NTSTATUSError
as error
:
541 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
542 raise CommandError("trusted domain object does not exist for domain [%s]" % domain
)
544 raise self
.LocalRuntimeError(self
, error
, "QueryTrustedDomainInfoByName(FULL_INFO) failed")
547 local_tdo_enctypes
= \
548 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
550 lsa
.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
)
551 except NTSTATUSError
as error
:
552 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_INVALID_PARAMETER
):
554 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_INVALID_INFO_CLASS
):
557 if error
is not None:
558 raise self
.LocalRuntimeError(self
, error
,
559 "QueryTrustedDomainInfoByName(SUPPORTED_ENCRYPTION_TYPES) failed")
561 local_tdo_enctypes
= lsa
.TrustDomainInfoSupportedEncTypes()
562 local_tdo_enctypes
.enc_types
= 0
565 local_tdo_forest
= None
566 if local_tdo_info
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
:
568 local_lsa
.lsaRQueryForestTrustInformation(local_policy
,
570 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
)
571 except RuntimeError as error
:
572 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
):
574 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_NOT_FOUND
):
576 if error
is not None:
577 raise self
.LocalRuntimeError(self
, error
, "lsaRQueryForestTrustInformation failed")
579 local_tdo_forest
= lsa
.ForestTrustInformation()
580 local_tdo_forest
.count
= 0
581 local_tdo_forest
.entries
= []
583 self
.outf
.write("TrustedDomain:\n\n")
584 self
.outf
.write("NetbiosName: %s\n" % local_tdo_info
.netbios_name
.string
)
585 if local_tdo_info
.netbios_name
.string
!= local_tdo_info
.domain_name
.string
:
586 self
.outf
.write("DnsName: %s\n" % local_tdo_info
.domain_name
.string
)
587 self
.outf
.write("SID: %s\n" % local_tdo_info
.sid
)
588 self
.outf
.write("Type: %s\n" % self
.trustType_string(local_tdo_info
.trust_type
))
589 self
.outf
.write("Direction: %s\n" % self
.trustDirection_string(local_tdo_info
.trust_direction
))
590 self
.outf
.write("Attributes: %s\n" % self
.trustAttributes_string(local_tdo_info
.trust_attributes
))
591 posix_offset_u32
= ctypes
.c_uint32(local_tdo_posix
.posix_offset
).value
592 posix_offset_i32
= ctypes
.c_int32(local_tdo_posix
.posix_offset
).value
593 self
.outf
.write("PosixOffset: 0x%08X (%d)\n" % (posix_offset_u32
, posix_offset_i32
))
594 self
.outf
.write("kerb_EncTypes: %s\n" % self
.kerb_EncTypes_string(local_tdo_enctypes
.enc_types
))
596 if local_tdo_info
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
:
597 self
.write_forest_trust_info(local_tdo_forest
,
598 tln
=local_tdo_info
.domain_name
.string
)
602 class cmd_domain_trust_modify(DomainTrustCommand
):
603 """Show trusted domain details."""
605 synopsis
= "%prog NAME [options]"
607 takes_optiongroups
= {
608 "sambaopts": options
.SambaOptions
,
609 "versionopts": options
.VersionOptions
,
610 "localdcopts": LocalDCCredentialsOptions
,
614 Option("--use-aes-keys", action
="store_true",
615 help="The trust uses AES kerberos keys.",
618 Option("--no-aes-keys", action
="store_true",
619 help="The trust does not have any support for AES kerberos keys.",
620 dest
='disable_aes_keys',
622 Option("--raw-kerb-enctypes", action
="store",
623 help="The raw kerberos enctype bits",
624 dest
='kerb_enctypes',
628 takes_args
= ["domain"]
630 def run(self
, domain
, sambaopts
=None, versionopts
=None, localdcopts
=None,
631 disable_aes_keys
=None, use_aes_keys
=None, kerb_enctypes
=None):
633 num_modifications
= 0
636 if kerb_enctypes
is not None:
638 if use_aes_keys
is not None:
640 if disable_aes_keys
is not None:
643 raise CommandError("--no-aes-keys, --use-aes-keys and --raw-kerb-enctypes are mutually exclusive")
644 if enctype_args
== 1:
645 num_modifications
+= 1
647 if num_modifications
== 0:
648 raise CommandError("modification arguments are required, try --help")
650 self
.setup_local_server(sambaopts
, localdcopts
)
652 local_lsa
= self
.new_local_lsa_connection()
653 except RuntimeError as error
:
654 raise self
.LocalRuntimeError(self
, error
, "failed to connect to lsa server")
657 local_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
661 local_revision_info1
,
663 ) = self
.get_lsa_info(local_lsa
, local_policy_access
)
664 except RuntimeError as error
:
665 raise self
.LocalRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
667 self
.outf
.write("LocalDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
668 local_lsa_info
.name
.string
,
669 local_lsa_info
.dns_domain
.string
,
672 if enctype_args
== 1:
673 lsaString
= lsa
.String()
674 lsaString
.string
= domain
677 local_tdo_enctypes
= \
678 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
680 lsa
.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
)
681 except NTSTATUSError
as error
:
682 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_INVALID_PARAMETER
):
684 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_INVALID_INFO_CLASS
):
687 if error
is not None:
688 raise self
.LocalRuntimeError(self
, error
,
689 "QueryTrustedDomainInfoByName(SUPPORTED_ENCRYPTION_TYPES) failed")
691 local_tdo_enctypes
= lsa
.TrustDomainInfoSupportedEncTypes()
692 local_tdo_enctypes
.enc_types
= 0
694 self
.outf
.write("Old kerb_EncTypes: %s\n" % self
.kerb_EncTypes_string(local_tdo_enctypes
.enc_types
))
696 enc_types
= lsa
.TrustDomainInfoSupportedEncTypes()
697 if kerb_enctypes
is not None:
698 enc_types
.enc_types
= int(kerb_enctypes
, base
=0)
699 elif use_aes_keys
is not None:
700 enc_types
.enc_types
= security
.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96
701 enc_types
.enc_types |
= security
.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96
702 elif disable_aes_keys
is not None:
703 # CVE-2022-37966: Trust objects are no longer assumed to support
704 # RC4, so we must indicate support explicitly.
705 enc_types
.enc_types
= security
.KERB_ENCTYPE_RC4_HMAC_MD5
707 raise CommandError("Internal error should be checked above")
709 if enc_types
.enc_types
!= local_tdo_enctypes
.enc_types
:
711 local_tdo_enctypes
= \
712 local_lsa
.SetTrustedDomainInfoByName(local_policy
,
714 lsa
.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
,
716 self
.outf
.write("New kerb_EncTypes: %s\n" % self
.kerb_EncTypes_string(enc_types
.enc_types
))
717 except NTSTATUSError
as error
:
718 if error
is not None:
719 raise self
.LocalRuntimeError(self
, error
,
720 "SetTrustedDomainInfoByName(SUPPORTED_ENCRYPTION_TYPES) failed")
722 self
.outf
.write("No kerb_EncTypes update needed\n")
726 class cmd_domain_trust_create(DomainTrustCommand
):
727 """Create a domain or forest trust."""
729 synopsis
= "%prog DOMAIN [options]"
731 takes_optiongroups
= {
732 "sambaopts": options
.SambaOptions
,
733 "versionopts": options
.VersionOptions
,
734 "credopts": options
.CredentialsOptions
,
735 "localdcopts": LocalDCCredentialsOptions
,
739 Option("--type", type="choice", metavar
="TYPE",
740 choices
=["external", "forest"],
741 help="The type of the trust: 'external' or 'forest'.",
744 Option("--direction", type="choice", metavar
="DIRECTION",
745 choices
=["incoming", "outgoing", "both"],
746 help="The trust direction: 'incoming', 'outgoing' or 'both'.",
747 dest
='trust_direction',
749 Option("--create-location", type="choice", metavar
="LOCATION",
750 choices
=["local", "both"],
751 help="Where to create the trusted domain object: 'local' or 'both'.",
752 dest
='create_location',
754 Option("--cross-organisation", action
="store_true",
755 help="The related domains does not belong to the same organisation.",
756 dest
='cross_organisation',
758 Option("--quarantined", type="choice", metavar
="yes|no",
759 choices
=["yes", "no", None],
760 help="Special SID filtering rules are applied to the trust. "
761 "With --type=external the default is yes. "
762 "With --type=forest the default is no.",
763 dest
='quarantined_arg',
765 Option("--not-transitive", action
="store_true",
766 help="The forest trust is not transitive.",
767 dest
='not_transitive',
769 Option("--treat-as-external", action
="store_true",
770 help="The treat the forest trust as external.",
771 dest
='treat_as_external',
773 Option("--no-aes-keys", action
="store_false",
774 help="The trust does not use AES kerberos keys.",
777 Option("--skip-validation", action
="store_false",
778 help="Skip validation of the trust.",
783 takes_args
= ["domain"]
785 def run(self
, domain
, sambaopts
=None, localdcopts
=None, credopts
=None, versionopts
=None,
786 trust_type
=None, trust_direction
=None, create_location
=None,
787 cross_organisation
=False, quarantined_arg
=None,
788 not_transitive
=False, treat_as_external
=False,
789 use_aes_keys
=False, validate
=True):
791 lsaString
= lsa
.String()
794 if quarantined_arg
is None:
795 if trust_type
== 'external':
797 elif quarantined_arg
== 'yes':
800 if trust_type
!= 'forest':
802 raise CommandError("--not-transitive requires --type=forest")
803 if treat_as_external
:
804 raise CommandError("--treat-as-external requires --type=forest")
806 enc_types
= lsa
.TrustDomainInfoSupportedEncTypes()
808 enc_types
.enc_types
= security
.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96
809 enc_types
.enc_types |
= security
.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96
811 # CVE-2022-37966: Trust objects are no longer assumed to support
812 # RC4, so we must indicate support explicitly.
813 enc_types
.enc_types
= security
.KERB_ENCTYPE_RC4_HMAC_MD5
815 local_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
816 local_policy_access |
= lsa
.LSA_POLICY_TRUST_ADMIN
817 local_policy_access |
= lsa
.LSA_POLICY_CREATE_SECRET
819 local_trust_info
= lsa
.TrustDomainInfoInfoEx()
820 local_trust_info
.trust_type
= lsa
.LSA_TRUST_TYPE_UPLEVEL
821 local_trust_info
.trust_direction
= 0
822 if trust_direction
== "both":
823 local_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_INBOUND
824 local_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_OUTBOUND
825 elif trust_direction
== "incoming":
826 local_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_INBOUND
827 elif trust_direction
== "outgoing":
828 local_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_OUTBOUND
829 local_trust_info
.trust_attributes
= 0
830 if cross_organisation
:
831 local_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION
833 local_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
834 if trust_type
== "forest":
835 local_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
837 local_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
838 if treat_as_external
:
839 local_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
841 def get_password(name
):
844 if password
is not None and password
!= '':
846 password
= getpass("New %s Password: " % name
)
847 passwordverify
= getpass("Retype %s Password: " % name
)
848 if not password
== passwordverify
:
850 self
.outf
.write("Sorry, passwords do not match.\n")
852 incoming_secret
= None
853 outgoing_secret
= None
854 remote_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
855 if create_location
== "local":
856 if local_trust_info
.trust_direction
& lsa
.LSA_TRUST_DIRECTION_INBOUND
:
857 incoming_password
= get_password("Incoming Trust")
858 incoming_secret
= list(incoming_password
.encode('utf-16-le'))
859 if local_trust_info
.trust_direction
& lsa
.LSA_TRUST_DIRECTION_OUTBOUND
:
860 outgoing_password
= get_password("Outgoing Trust")
861 outgoing_secret
= list(outgoing_password
.encode('utf-16-le'))
863 remote_trust_info
= None
865 # We use 240 random bytes.
866 # Windows uses 28 or 240 random bytes. I guess it's
867 # based on the trust type external vs. forest.
869 # The initial trust password can be up to 512 bytes
870 # while the versioned passwords used for periodic updates
871 # can only be up to 498 bytes, as netr_ServerPasswordSet2()
872 # needs to pass the NL_PASSWORD_VERSION structure within the
873 # 512 bytes and a 2 bytes confounder is required.
875 def random_trust_secret(length
):
876 pw
= samba
.generate_random_machine_password(length
// 2, length
// 2)
877 return list(pw
.encode('utf-16-le'))
879 if local_trust_info
.trust_direction
& lsa
.LSA_TRUST_DIRECTION_INBOUND
:
880 incoming_secret
= random_trust_secret(240)
881 if local_trust_info
.trust_direction
& lsa
.LSA_TRUST_DIRECTION_OUTBOUND
:
882 outgoing_secret
= random_trust_secret(240)
884 remote_policy_access |
= lsa
.LSA_POLICY_TRUST_ADMIN
885 remote_policy_access |
= lsa
.LSA_POLICY_CREATE_SECRET
887 remote_trust_info
= lsa
.TrustDomainInfoInfoEx()
888 remote_trust_info
.trust_type
= lsa
.LSA_TRUST_TYPE_UPLEVEL
889 remote_trust_info
.trust_direction
= 0
890 if trust_direction
== "both":
891 remote_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_INBOUND
892 remote_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_OUTBOUND
893 elif trust_direction
== "incoming":
894 remote_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_OUTBOUND
895 elif trust_direction
== "outgoing":
896 remote_trust_info
.trust_direction |
= lsa
.LSA_TRUST_DIRECTION_INBOUND
897 remote_trust_info
.trust_attributes
= 0
898 if cross_organisation
:
899 remote_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION
901 remote_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
902 if trust_type
== "forest":
903 remote_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
905 remote_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
906 if treat_as_external
:
907 remote_trust_info
.trust_attributes |
= lsa
.LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
909 local_server
= self
.setup_local_server(sambaopts
, localdcopts
)
911 local_lsa
= self
.new_local_lsa_connection()
912 except RuntimeError as error
:
913 raise self
.LocalRuntimeError(self
, error
, "failed to connect lsa server")
919 local_revision_info1
,
921 ) = self
.get_lsa_info(local_lsa
, local_policy_access
)
922 except RuntimeError as error
:
923 raise self
.LocalRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
925 self
.outf
.write("LocalDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
926 local_lsa_info
.name
.string
,
927 local_lsa_info
.dns_domain
.string
,
931 remote_server
= self
.setup_remote_server(credopts
, domain
)
932 except RuntimeError as error
:
933 raise self
.RemoteRuntimeError(self
, error
, "failed to locate remote server")
936 remote_lsa
= self
.new_remote_lsa_connection()
937 except RuntimeError as error
:
938 raise self
.RemoteRuntimeError(self
, error
, "failed to connect lsa server")
944 remote_revision_info1
,
946 ) = self
.get_lsa_info(remote_lsa
, remote_policy_access
)
947 except RuntimeError as error
:
948 raise self
.RemoteRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
950 self
.outf
.write("RemoteDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
951 remote_lsa_info
.name
.string
,
952 remote_lsa_info
.dns_domain
.string
,
953 remote_lsa_info
.sid
))
955 local_trust_info
.domain_name
.string
= remote_lsa_info
.dns_domain
.string
956 local_trust_info
.netbios_name
.string
= remote_lsa_info
.name
.string
957 local_trust_info
.sid
= remote_lsa_info
.sid
959 if remote_trust_info
:
960 remote_trust_info
.domain_name
.string
= local_lsa_info
.dns_domain
.string
961 remote_trust_info
.netbios_name
.string
= local_lsa_info
.name
.string
962 remote_trust_info
.sid
= local_lsa_info
.sid
965 lsaString
.string
= local_trust_info
.domain_name
.string
966 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
968 lsa
.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
)
969 raise CommandError("TrustedDomain %s already exist'" % lsaString
.string
)
970 except NTSTATUSError
as error
:
971 if not self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
972 raise self
.LocalRuntimeError(self
, error
,
973 "QueryTrustedDomainInfoByName(%s, FULL_INFO) failed" % (
977 lsaString
.string
= local_trust_info
.netbios_name
.string
978 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
980 lsa
.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
)
981 raise CommandError("TrustedDomain %s already exist'" % lsaString
.string
)
982 except NTSTATUSError
as error
:
983 if not self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
984 raise self
.LocalRuntimeError(self
, error
,
985 "QueryTrustedDomainInfoByName(%s, FULL_INFO) failed" % (
988 if remote_trust_info
:
990 lsaString
.string
= remote_trust_info
.domain_name
.string
991 remote_lsa
.QueryTrustedDomainInfoByName(remote_policy
,
993 lsa
.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
)
994 raise CommandError("TrustedDomain %s already exist'" % lsaString
.string
)
995 except NTSTATUSError
as error
:
996 if not self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
997 raise self
.RemoteRuntimeError(self
, error
,
998 "QueryTrustedDomainInfoByName(%s, FULL_INFO) failed" % (
1002 lsaString
.string
= remote_trust_info
.netbios_name
.string
1003 remote_lsa
.QueryTrustedDomainInfoByName(remote_policy
,
1005 lsa
.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
)
1006 raise CommandError("TrustedDomain %s already exist'" % lsaString
.string
)
1007 except NTSTATUSError
as error
:
1008 if not self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
1009 raise self
.RemoteRuntimeError(self
, error
,
1010 "QueryTrustedDomainInfoByName(%s, FULL_INFO) failed" % (
1014 local_netlogon
= self
.new_local_netlogon_connection()
1015 except RuntimeError as error
:
1016 raise self
.LocalRuntimeError(self
, error
, "failed to connect netlogon server")
1019 local_netlogon_info
= self
.get_netlogon_dc_info(local_netlogon
, local_server
)
1020 except RuntimeError as error
:
1021 raise self
.LocalRuntimeError(self
, error
, "failed to get netlogon dc info")
1023 if remote_trust_info
:
1025 remote_netlogon
= self
.new_remote_netlogon_connection()
1026 except RuntimeError as error
:
1027 raise self
.RemoteRuntimeError(self
, error
, "failed to connect netlogon server")
1030 remote_netlogon_dc_unc
= self
.get_netlogon_dc_unc(remote_netlogon
,
1031 remote_server
, domain
)
1032 except RuntimeError as error
:
1033 raise self
.RemoteRuntimeError(self
, error
, "failed to get netlogon dc info")
1035 def generate_AuthInOutBlob(secret
, update_time
):
1037 blob
= drsblobs
.trustAuthInOutBlob()
1042 clear
= drsblobs
.AuthInfoClear()
1043 clear
.size
= len(secret
)
1044 clear
.password
= secret
1046 info
= drsblobs
.AuthenticationInformation()
1047 info
.LastUpdateTime
= samba
.unix2nttime(update_time
)
1048 info
.AuthType
= lsa
.TRUST_AUTH_TYPE_CLEAR
1049 info
.AuthInfo
= clear
1051 array
= drsblobs
.AuthenticationInformationArray()
1053 array
.array
= [info
]
1055 blob
= drsblobs
.trustAuthInOutBlob()
1057 blob
.current
= array
1061 update_time
= samba
.current_unix_time()
1062 incoming_blob
= generate_AuthInOutBlob(incoming_secret
, update_time
)
1063 outgoing_blob
= generate_AuthInOutBlob(outgoing_secret
, update_time
)
1065 local_tdo_handle
= None
1066 remote_tdo_handle
= None
1069 if remote_trust_info
:
1070 self
.outf
.write("Creating remote TDO.\n")
1071 current_request
= {"location": "remote", "name": "CreateTrustedDomainEx2"}
1072 remote_tdo_handle
= CreateTrustedDomainFallback(
1076 lsa
.LSA_TRUSTED_DOMAIN_ALL_ACCESS
,
1078 remote_revision_info1
,
1082 self
.outf
.write("Remote TDO created.\n")
1084 self
.outf
.write("Setting supported encryption types on remote TDO.\n")
1085 current_request
= {"location": "remote", "name": "SetInformationTrustedDomain"}
1086 remote_lsa
.SetInformationTrustedDomain(remote_tdo_handle
,
1087 lsa
.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
,
1090 self
.outf
.write("Creating local TDO.\n")
1091 current_request
= {"location": "local", "name": "CreateTrustedDomainEx2"}
1092 local_tdo_handle
= CreateTrustedDomainFallback(
1096 lsa
.LSA_TRUSTED_DOMAIN_ALL_ACCESS
,
1098 local_revision_info1
,
1102 self
.outf
.write("Local TDO created\n")
1104 self
.outf
.write("Setting supported encryption types on local TDO.\n")
1105 current_request
= {"location": "local", "name": "SetInformationTrustedDomain"}
1106 local_lsa
.SetInformationTrustedDomain(local_tdo_handle
,
1107 lsa
.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
,
1109 except RuntimeError as error
:
1110 self
.outf
.write("Error: %s failed %sly - cleaning up\n" % (
1111 current_request
['name'], current_request
['location']))
1112 if remote_tdo_handle
:
1113 self
.outf
.write("Deleting remote TDO.\n")
1114 remote_lsa
.DeleteObject(remote_tdo_handle
)
1115 remote_tdo_handle
= None
1116 if local_tdo_handle
:
1117 self
.outf
.write("Deleting local TDO.\n")
1118 local_lsa
.DeleteObject(local_tdo_handle
)
1119 local_tdo_handle
= None
1120 if current_request
['location'] == "remote":
1121 raise self
.RemoteRuntimeError(self
, error
, "%s" % (
1122 current_request
['name']))
1123 raise self
.LocalRuntimeError(self
, error
, "%s" % (
1124 current_request
['name']))
1127 if local_trust_info
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
:
1128 self
.outf
.write("Setup local forest trust information...\n")
1130 # get all information about the remote trust
1131 # this triggers netr_GetForestTrustInformation to the remote domain
1132 # and lsaRSetForestTrustInformation() locally, but new top level
1133 # names are disabled by default.
1134 local_forest_info
= \
1135 local_netlogon
.netr_DsRGetForestTrustInformation(local_netlogon_info
.dc_unc
,
1136 remote_lsa_info
.dns_domain
.string
,
1137 netlogon
.DS_GFTI_UPDATE_TDO
)
1138 except RuntimeError as error
:
1139 raise self
.LocalRuntimeError(self
, error
, "netr_DsRGetForestTrustInformation() failed")
1142 # here we try to enable all top level names
1143 local_forest_collision
= \
1144 local_lsa
.lsaRSetForestTrustInformation(local_policy
,
1145 remote_lsa_info
.dns_domain
,
1146 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
,
1149 except RuntimeError as error
:
1150 raise self
.LocalRuntimeError(self
, error
, "lsaRSetForestTrustInformation() failed")
1152 self
.write_forest_trust_info(local_forest_info
,
1153 tln
=remote_lsa_info
.dns_domain
.string
,
1154 collisions
=local_forest_collision
)
1156 if remote_trust_info
:
1157 self
.outf
.write("Setup remote forest trust information...\n")
1159 # get all information about the local trust (from the perspective of the remote domain)
1160 # this triggers netr_GetForestTrustInformation to our domain.
1161 # and lsaRSetForestTrustInformation() remotely, but new top level
1162 # names are disabled by default.
1163 remote_forest_info
= \
1164 remote_netlogon
.netr_DsRGetForestTrustInformation(remote_netlogon_dc_unc
,
1165 local_lsa_info
.dns_domain
.string
,
1166 netlogon
.DS_GFTI_UPDATE_TDO
)
1167 except RuntimeError as error
:
1168 raise self
.RemoteRuntimeError(self
, error
, "netr_DsRGetForestTrustInformation() failed")
1171 # here we try to enable all top level names
1172 remote_forest_collision
= \
1173 remote_lsa
.lsaRSetForestTrustInformation(remote_policy
,
1174 local_lsa_info
.dns_domain
,
1175 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
,
1178 except RuntimeError as error
:
1179 raise self
.RemoteRuntimeError(self
, error
, "lsaRSetForestTrustInformation() failed")
1181 self
.write_forest_trust_info(remote_forest_info
,
1182 tln
=local_lsa_info
.dns_domain
.string
,
1183 collisions
=remote_forest_collision
)
1185 if local_trust_info
.trust_direction
& lsa
.LSA_TRUST_DIRECTION_OUTBOUND
:
1186 self
.outf
.write("Validating outgoing trust...\n")
1188 local_trust_verify
= local_netlogon
.netr_LogonControl2Ex(local_netlogon_info
.dc_unc
,
1189 netlogon
.NETLOGON_CONTROL_TC_VERIFY
,
1191 remote_lsa_info
.dns_domain
.string
)
1192 except RuntimeError as error
:
1193 raise self
.LocalRuntimeError(self
, error
, "NETLOGON_CONTROL_TC_VERIFY failed")
1195 local_trust_status
= self
._uint
32(local_trust_verify
.pdc_connection_status
[0])
1196 local_conn_status
= self
._uint
32(local_trust_verify
.tc_connection_status
[0])
1198 if local_trust_verify
.flags
& netlogon
.NETLOGON_VERIFY_STATUS_RETURNED
:
1199 local_validation
= "LocalValidation: DC[%s] CONNECTION[%s] TRUST[%s] VERIFY_STATUS_RETURNED" % (
1200 local_trust_verify
.trusted_dc_name
,
1201 local_trust_verify
.tc_connection_status
[1],
1202 local_trust_verify
.pdc_connection_status
[1])
1204 local_validation
= "LocalValidation: DC[%s] CONNECTION[%s] TRUST[%s]" % (
1205 local_trust_verify
.trusted_dc_name
,
1206 local_trust_verify
.tc_connection_status
[1],
1207 local_trust_verify
.pdc_connection_status
[1])
1209 if local_trust_status
!= werror
.WERR_SUCCESS
or local_conn_status
!= werror
.WERR_SUCCESS
:
1210 raise CommandError(local_validation
)
1212 self
.outf
.write("OK: %s\n" % local_validation
)
1214 if remote_trust_info
:
1215 if remote_trust_info
.trust_direction
& lsa
.LSA_TRUST_DIRECTION_OUTBOUND
:
1216 self
.outf
.write("Validating incoming trust...\n")
1218 remote_trust_verify
= \
1219 remote_netlogon
.netr_LogonControl2Ex(remote_netlogon_dc_unc
,
1220 netlogon
.NETLOGON_CONTROL_TC_VERIFY
,
1222 local_lsa_info
.dns_domain
.string
)
1223 except RuntimeError as error
:
1224 raise self
.RemoteRuntimeError(self
, error
, "NETLOGON_CONTROL_TC_VERIFY failed")
1226 remote_trust_status
= self
._uint
32(remote_trust_verify
.pdc_connection_status
[0])
1227 remote_conn_status
= self
._uint
32(remote_trust_verify
.tc_connection_status
[0])
1229 if remote_trust_verify
.flags
& netlogon
.NETLOGON_VERIFY_STATUS_RETURNED
:
1230 remote_validation
= "RemoteValidation: DC[%s] CONNECTION[%s] TRUST[%s] VERIFY_STATUS_RETURNED" % (
1231 remote_trust_verify
.trusted_dc_name
,
1232 remote_trust_verify
.tc_connection_status
[1],
1233 remote_trust_verify
.pdc_connection_status
[1])
1235 remote_validation
= "RemoteValidation: DC[%s] CONNECTION[%s] TRUST[%s]" % (
1236 remote_trust_verify
.trusted_dc_name
,
1237 remote_trust_verify
.tc_connection_status
[1],
1238 remote_trust_verify
.pdc_connection_status
[1])
1240 if remote_trust_status
!= werror
.WERR_SUCCESS
or remote_conn_status
!= werror
.WERR_SUCCESS
:
1241 raise CommandError(remote_validation
)
1243 self
.outf
.write("OK: %s\n" % remote_validation
)
1245 if remote_tdo_handle
is not None:
1247 remote_lsa
.Close(remote_tdo_handle
)
1248 except RuntimeError:
1250 remote_tdo_handle
= None
1251 if local_tdo_handle
is not None:
1253 local_lsa
.Close(local_tdo_handle
)
1254 except RuntimeError:
1256 local_tdo_handle
= None
1258 self
.outf
.write("Success.\n")
1262 class cmd_domain_trust_delete(DomainTrustCommand
):
1263 """Delete a domain trust."""
1265 synopsis
= "%prog DOMAIN [options]"
1267 takes_optiongroups
= {
1268 "sambaopts": options
.SambaOptions
,
1269 "versionopts": options
.VersionOptions
,
1270 "credopts": options
.CredentialsOptions
,
1271 "localdcopts": LocalDCCredentialsOptions
,
1275 Option("--delete-location", type="choice", metavar
="LOCATION",
1276 choices
=["local", "both"],
1277 help="Where to delete the trusted domain object: 'local' or 'both'.",
1278 dest
='delete_location',
1282 takes_args
= ["domain"]
1284 def run(self
, domain
, sambaopts
=None, localdcopts
=None, credopts
=None, versionopts
=None,
1285 delete_location
=None):
1287 local_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
1288 local_policy_access |
= lsa
.LSA_POLICY_TRUST_ADMIN
1289 local_policy_access |
= lsa
.LSA_POLICY_CREATE_SECRET
1291 if delete_location
== "local":
1292 remote_policy_access
= None
1294 remote_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
1295 remote_policy_access |
= lsa
.LSA_POLICY_TRUST_ADMIN
1296 remote_policy_access |
= lsa
.LSA_POLICY_CREATE_SECRET
1298 self
.setup_local_server(sambaopts
, localdcopts
)
1300 local_lsa
= self
.new_local_lsa_connection()
1301 except RuntimeError as error
:
1302 raise self
.LocalRuntimeError(self
, error
, "failed to connect lsa server")
1308 local_revision_info1
,
1310 ) = self
.get_lsa_info(local_lsa
, local_policy_access
)
1311 except RuntimeError as error
:
1312 raise self
.LocalRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
1314 self
.outf
.write("LocalDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
1315 local_lsa_info
.name
.string
,
1316 local_lsa_info
.dns_domain
.string
,
1317 local_lsa_info
.sid
))
1319 local_tdo_info
= None
1320 local_tdo_handle
= None
1321 remote_tdo_info
= None
1322 remote_tdo_handle
= None
1324 lsaString
= lsa
.String()
1326 lsaString
.string
= domain
1327 local_tdo_info
= local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
1328 lsaString
, lsa
.LSA_TRUSTED_DOMAIN_INFO_INFO_EX
)
1329 except NTSTATUSError
as error
:
1330 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
1331 raise CommandError("Failed to find trust for domain '%s'" % domain
)
1332 raise self
.RemoteRuntimeError(self
, error
, "failed to locate remote server")
1334 if remote_policy_access
is not None:
1336 self
.setup_remote_server(credopts
, domain
)
1337 except RuntimeError as error
:
1338 raise self
.RemoteRuntimeError(self
, error
, "failed to locate remote server")
1341 remote_lsa
= self
.new_remote_lsa_connection()
1342 except RuntimeError as error
:
1343 raise self
.RemoteRuntimeError(self
, error
, "failed to connect lsa server")
1349 remote_revision_info1
,
1351 ) = self
.get_lsa_info(remote_lsa
, remote_policy_access
)
1352 except RuntimeError as error
:
1353 raise self
.RemoteRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
1355 self
.outf
.write("RemoteDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
1356 remote_lsa_info
.name
.string
,
1357 remote_lsa_info
.dns_domain
.string
,
1358 remote_lsa_info
.sid
))
1360 if remote_lsa_info
.sid
!= local_tdo_info
.sid
or \
1361 remote_lsa_info
.name
.string
!= local_tdo_info
.netbios_name
.string
or \
1362 remote_lsa_info
.dns_domain
.string
!= local_tdo_info
.domain_name
.string
:
1363 raise CommandError("LocalTDO inconsistent: Netbios[%s] DNS[%s] SID[%s]" % (
1364 local_tdo_info
.netbios_name
.string
,
1365 local_tdo_info
.domain_name
.string
,
1366 local_tdo_info
.sid
))
1369 lsaString
.string
= local_lsa_info
.dns_domain
.string
1371 remote_lsa
.QueryTrustedDomainInfoByName(remote_policy
,
1373 lsa
.LSA_TRUSTED_DOMAIN_INFO_INFO_EX
)
1374 except NTSTATUSError
as error
:
1375 if not self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
1376 raise self
.RemoteRuntimeError(self
, error
, "QueryTrustedDomainInfoByName(%s)" % (
1379 if remote_tdo_info
is not None:
1380 if local_lsa_info
.sid
!= remote_tdo_info
.sid
or \
1381 local_lsa_info
.name
.string
!= remote_tdo_info
.netbios_name
.string
or \
1382 local_lsa_info
.dns_domain
.string
!= remote_tdo_info
.domain_name
.string
:
1383 raise CommandError("RemoteTDO inconsistent: Netbios[%s] DNS[%s] SID[%s]" % (
1384 remote_tdo_info
.netbios_name
.string
,
1385 remote_tdo_info
.domain_name
.string
,
1386 remote_tdo_info
.sid
))
1388 if local_tdo_info
is not None:
1390 lsaString
.string
= local_tdo_info
.domain_name
.string
1391 local_tdo_handle
= \
1392 local_lsa
.OpenTrustedDomainByName(local_policy
,
1394 security
.SEC_STD_DELETE
)
1395 except RuntimeError as error
:
1396 raise self
.LocalRuntimeError(self
, error
, "OpenTrustedDomainByName(%s)" % (
1399 local_lsa
.DeleteObject(local_tdo_handle
)
1400 local_tdo_handle
= None
1402 if remote_tdo_info
is not None:
1404 lsaString
.string
= remote_tdo_info
.domain_name
.string
1405 remote_tdo_handle
= \
1406 remote_lsa
.OpenTrustedDomainByName(remote_policy
,
1408 security
.SEC_STD_DELETE
)
1409 except RuntimeError as error
:
1410 raise self
.RemoteRuntimeError(self
, error
, "OpenTrustedDomainByName(%s)" % (
1413 if remote_tdo_handle
is not None:
1415 remote_lsa
.DeleteObject(remote_tdo_handle
)
1416 remote_tdo_handle
= None
1417 self
.outf
.write("RemoteTDO deleted.\n")
1418 except RuntimeError as error
:
1419 self
.outf
.write("%s\n" % self
.RemoteRuntimeError(self
, error
, "DeleteObject() failed"))
1424 class cmd_domain_trust_validate(DomainTrustCommand
):
1425 """Validate a domain trust."""
1427 synopsis
= "%prog DOMAIN [options]"
1429 takes_optiongroups
= {
1430 "sambaopts": options
.SambaOptions
,
1431 "versionopts": options
.VersionOptions
,
1432 "credopts": options
.CredentialsOptions
,
1433 "localdcopts": LocalDCCredentialsOptions
,
1437 Option("--validate-location", type="choice", metavar
="LOCATION",
1438 choices
=["local", "both"],
1439 help="Where to validate the trusted domain object: 'local' or 'both'.",
1440 dest
='validate_location',
1444 takes_args
= ["domain"]
1446 def run(self
, domain
, sambaopts
=None, versionopts
=None, credopts
=None, localdcopts
=None,
1447 validate_location
=None):
1449 local_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
1451 local_server
= self
.setup_local_server(sambaopts
, localdcopts
)
1453 local_lsa
= self
.new_local_lsa_connection()
1454 except RuntimeError as error
:
1455 raise self
.LocalRuntimeError(self
, error
, "failed to connect lsa server")
1461 local_revision_info1
,
1463 ) = self
.get_lsa_info(local_lsa
, local_policy_access
)
1464 except RuntimeError as error
:
1465 raise self
.LocalRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
1467 self
.outf
.write("LocalDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
1468 local_lsa_info
.name
.string
,
1469 local_lsa_info
.dns_domain
.string
,
1470 local_lsa_info
.sid
))
1473 lsaString
= lsa
.String()
1474 lsaString
.string
= domain
1476 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
1478 lsa
.LSA_TRUSTED_DOMAIN_INFO_INFO_EX
)
1479 except NTSTATUSError
as error
:
1480 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
1481 raise CommandError("trusted domain object does not exist for domain [%s]" % domain
)
1483 raise self
.LocalRuntimeError(self
, error
, "QueryTrustedDomainInfoByName(INFO_EX) failed")
1485 self
.outf
.write("LocalTDO Netbios[%s] DNS[%s] SID[%s]\n" % (
1486 local_tdo_info
.netbios_name
.string
,
1487 local_tdo_info
.domain_name
.string
,
1488 local_tdo_info
.sid
))
1491 local_netlogon
= self
.new_local_netlogon_connection()
1492 except RuntimeError as error
:
1493 raise self
.LocalRuntimeError(self
, error
, "failed to connect netlogon server")
1496 local_trust_verify
= \
1497 local_netlogon
.netr_LogonControl2Ex(local_server
,
1498 netlogon
.NETLOGON_CONTROL_TC_VERIFY
,
1500 local_tdo_info
.domain_name
.string
)
1501 except RuntimeError as error
:
1502 raise self
.LocalRuntimeError(self
, error
, "NETLOGON_CONTROL_TC_VERIFY failed")
1504 local_trust_status
= self
._uint
32(local_trust_verify
.pdc_connection_status
[0])
1505 local_conn_status
= self
._uint
32(local_trust_verify
.tc_connection_status
[0])
1507 if local_trust_verify
.flags
& netlogon
.NETLOGON_VERIFY_STATUS_RETURNED
:
1508 local_validation
= "LocalValidation: DC[%s] CONNECTION[%s] TRUST[%s] VERIFY_STATUS_RETURNED" % (
1509 local_trust_verify
.trusted_dc_name
,
1510 local_trust_verify
.tc_connection_status
[1],
1511 local_trust_verify
.pdc_connection_status
[1])
1513 local_validation
= "LocalValidation: DC[%s] CONNECTION[%s] TRUST[%s]" % (
1514 local_trust_verify
.trusted_dc_name
,
1515 local_trust_verify
.tc_connection_status
[1],
1516 local_trust_verify
.pdc_connection_status
[1])
1518 if local_trust_status
!= werror
.WERR_SUCCESS
or local_conn_status
!= werror
.WERR_SUCCESS
:
1519 raise CommandError(local_validation
)
1521 self
.outf
.write("OK: %s\n" % local_validation
)
1524 server
= local_trust_verify
.trusted_dc_name
.replace('\\', '')
1525 domain_and_server
= "%s\\%s" % (local_tdo_info
.domain_name
.string
, server
)
1526 local_trust_rediscover
= \
1527 local_netlogon
.netr_LogonControl2Ex(local_server
,
1528 netlogon
.NETLOGON_CONTROL_REDISCOVER
,
1531 except RuntimeError as error
:
1532 raise self
.LocalRuntimeError(self
, error
, "NETLOGON_CONTROL_REDISCOVER failed")
1534 local_conn_status
= self
._uint
32(local_trust_rediscover
.tc_connection_status
[0])
1535 local_rediscover
= "LocalRediscover: DC[%s] CONNECTION[%s]" % (
1536 local_trust_rediscover
.trusted_dc_name
,
1537 local_trust_rediscover
.tc_connection_status
[1])
1539 if local_conn_status
!= werror
.WERR_SUCCESS
:
1540 raise CommandError(local_rediscover
)
1542 self
.outf
.write("OK: %s\n" % local_rediscover
)
1544 if validate_location
!= "local":
1546 remote_server
= self
.setup_remote_server(credopts
, domain
, require_pdc
=False)
1547 except RuntimeError as error
:
1548 raise self
.RemoteRuntimeError(self
, error
, "failed to locate remote server")
1551 remote_netlogon
= self
.new_remote_netlogon_connection()
1552 except RuntimeError as error
:
1553 raise self
.RemoteRuntimeError(self
, error
, "failed to connect netlogon server")
1556 remote_trust_verify
= \
1557 remote_netlogon
.netr_LogonControl2Ex(remote_server
,
1558 netlogon
.NETLOGON_CONTROL_TC_VERIFY
,
1560 local_lsa_info
.dns_domain
.string
)
1561 except RuntimeError as error
:
1562 raise self
.RemoteRuntimeError(self
, error
, "NETLOGON_CONTROL_TC_VERIFY failed")
1564 remote_trust_status
= self
._uint
32(remote_trust_verify
.pdc_connection_status
[0])
1565 remote_conn_status
= self
._uint
32(remote_trust_verify
.tc_connection_status
[0])
1567 if remote_trust_verify
.flags
& netlogon
.NETLOGON_VERIFY_STATUS_RETURNED
:
1568 remote_validation
= "RemoteValidation: DC[%s] CONNECTION[%s] TRUST[%s] VERIFY_STATUS_RETURNED" % (
1569 remote_trust_verify
.trusted_dc_name
,
1570 remote_trust_verify
.tc_connection_status
[1],
1571 remote_trust_verify
.pdc_connection_status
[1])
1573 remote_validation
= "RemoteValidation: DC[%s] CONNECTION[%s] TRUST[%s]" % (
1574 remote_trust_verify
.trusted_dc_name
,
1575 remote_trust_verify
.tc_connection_status
[1],
1576 remote_trust_verify
.pdc_connection_status
[1])
1578 if remote_trust_status
!= werror
.WERR_SUCCESS
or remote_conn_status
!= werror
.WERR_SUCCESS
:
1579 raise CommandError(remote_validation
)
1581 self
.outf
.write("OK: %s\n" % remote_validation
)
1584 server
= remote_trust_verify
.trusted_dc_name
.replace('\\', '')
1585 domain_and_server
= "%s\\%s" % (local_lsa_info
.dns_domain
.string
, server
)
1586 remote_trust_rediscover
= \
1587 remote_netlogon
.netr_LogonControl2Ex(remote_server
,
1588 netlogon
.NETLOGON_CONTROL_REDISCOVER
,
1591 except RuntimeError as error
:
1592 raise self
.RemoteRuntimeError(self
, error
, "NETLOGON_CONTROL_REDISCOVER failed")
1594 remote_conn_status
= self
._uint
32(remote_trust_rediscover
.tc_connection_status
[0])
1596 remote_rediscover
= "RemoteRediscover: DC[%s] CONNECTION[%s]" % (
1597 remote_trust_rediscover
.trusted_dc_name
,
1598 remote_trust_rediscover
.tc_connection_status
[1])
1600 if remote_conn_status
!= werror
.WERR_SUCCESS
:
1601 raise CommandError(remote_rediscover
)
1603 self
.outf
.write("OK: %s\n" % remote_rediscover
)
1608 class cmd_domain_trust_namespaces(DomainTrustCommand
):
1609 """Manage forest trust namespaces."""
1611 synopsis
= "%prog [DOMAIN] [options]"
1613 takes_optiongroups
= {
1614 "sambaopts": options
.SambaOptions
,
1615 "versionopts": options
.VersionOptions
,
1616 "localdcopts": LocalDCCredentialsOptions
,
1620 Option("--refresh", type="choice", metavar
="check|store",
1621 choices
=["check", "store", None],
1622 help="List and maybe store refreshed forest trust information: 'check' or 'store'.",
1625 Option("--enable-all", action
="store_true",
1626 help="Try to update disabled entries, not allowed with --refresh=check.",
1629 Option("--enable-tln", action
="append", metavar
='DNSDOMAIN',
1630 help="Enable a top level name entry. Can be specified multiple times.",
1633 Option("--disable-tln", action
="append", metavar
='DNSDOMAIN',
1634 help="Disable a top level name entry. Can be specified multiple times.",
1637 Option("--add-tln-ex", action
="append", metavar
='DNSDOMAIN',
1638 help="Add a top level exclusion entry. Can be specified multiple times.",
1641 Option("--delete-tln-ex", action
="append", metavar
='DNSDOMAIN',
1642 help="Delete a top level exclusion entry. Can be specified multiple times.",
1643 dest
='delete_tln_ex',
1645 Option("--enable-nb", action
="append", metavar
='NETBIOSDOMAIN',
1646 help="Enable a netbios name in a domain entry. Can be specified multiple times.",
1649 Option("--disable-nb", action
="append", metavar
='NETBIOSDOMAIN',
1650 help="Disable a netbios name in a domain entry. Can be specified multiple times.",
1653 Option("--enable-sid", action
="append", metavar
='DOMAINSID',
1654 help="Enable a SID in a domain entry. Can be specified multiple times.",
1655 dest
='enable_sid_str',
1657 Option("--disable-sid", action
="append", metavar
='DOMAINSID',
1658 help="Disable a SID in a domain entry. Can be specified multiple times.",
1659 dest
='disable_sid_str',
1661 Option("--add-upn-suffix", action
="append", metavar
='DNSDOMAIN',
1662 help="Add a new uPNSuffixes attribute for the local forest. Can be specified multiple times.",
1665 Option("--delete-upn-suffix", action
="append", metavar
='DNSDOMAIN',
1666 help="Delete an existing uPNSuffixes attribute of the local forest. Can be specified multiple times.",
1669 Option("--add-spn-suffix", action
="append", metavar
='DNSDOMAIN',
1670 help="Add a new msDS-SPNSuffixes attribute for the local forest. Can be specified multiple times.",
1673 Option("--delete-spn-suffix", action
="append", metavar
='DNSDOMAIN',
1674 help="Delete an existing msDS-SPNSuffixes attribute of the local forest. Can be specified multiple times.",
1679 takes_args
= ["domain?"]
1681 def run(self
, domain
=None, sambaopts
=None, localdcopts
=None, versionopts
=None,
1682 refresh
=None, enable_all
=False,
1683 enable_tln
=None, disable_tln
=None, add_tln_ex
=None, delete_tln_ex
=None,
1684 enable_sid_str
=None, disable_sid_str
=None, enable_nb
=None, disable_nb
=None,
1685 add_upn
=None, delete_upn
=None, add_spn
=None, delete_spn
=None):
1687 if enable_tln
is None:
1689 if disable_tln
is None:
1691 if add_tln_ex
is None:
1693 if delete_tln_ex
is None:
1695 if enable_sid_str
is None:
1697 if disable_sid_str
is None:
1698 disable_sid_str
= []
1699 if enable_nb
is None:
1701 if disable_nb
is None:
1705 if delete_upn
is None:
1709 if delete_spn
is None:
1712 require_update
= False
1715 if refresh
== "store":
1716 raise CommandError("--refresh=%s not allowed without DOMAIN" % refresh
)
1719 raise CommandError("--enable-all not allowed without DOMAIN")
1721 if len(enable_tln
) > 0:
1722 raise CommandError("--enable-tln not allowed without DOMAIN")
1723 if len(disable_tln
) > 0:
1724 raise CommandError("--disable-tln not allowed without DOMAIN")
1726 if len(add_tln_ex
) > 0:
1727 raise CommandError("--add-tln-ex not allowed without DOMAIN")
1728 if len(delete_tln_ex
) > 0:
1729 raise CommandError("--delete-tln-ex not allowed without DOMAIN")
1731 if len(enable_nb
) > 0:
1732 raise CommandError("--enable-nb not allowed without DOMAIN")
1733 if len(disable_nb
) > 0:
1734 raise CommandError("--disable-nb not allowed without DOMAIN")
1736 if len(enable_sid_str
) > 0:
1737 raise CommandError("--enable-sid not allowed without DOMAIN")
1738 if len(disable_sid_str
) > 0:
1739 raise CommandError("--disable-sid not allowed without DOMAIN")
1741 if len(add_upn
) > 0:
1743 if not n
.startswith("*."):
1745 raise CommandError("value[%s] specified for --add-upn-suffix should not include with '*.'" % n
)
1746 require_update
= True
1747 if len(delete_upn
) > 0:
1748 for n
in delete_upn
:
1749 if not n
.startswith("*."):
1751 raise CommandError("value[%s] specified for --delete-upn-suffix should not include with '*.'" % n
)
1752 require_update
= True
1754 for d
in delete_upn
:
1755 if a
.lower() != d
.lower():
1757 raise CommandError("value[%s] specified for --add-upn-suffix and --delete-upn-suffix" % a
)
1759 if len(add_spn
) > 0:
1761 if not n
.startswith("*."):
1763 raise CommandError("value[%s] specified for --add-spn-suffix should not include with '*.'" % n
)
1764 require_update
= True
1765 if len(delete_spn
) > 0:
1766 for n
in delete_spn
:
1767 if not n
.startswith("*."):
1769 raise CommandError("value[%s] specified for --delete-spn-suffix should not include with '*.'" % n
)
1770 require_update
= True
1772 for d
in delete_spn
:
1773 if a
.lower() != d
.lower():
1775 raise CommandError("value[%s] specified for --add-spn-suffix and --delete-spn-suffix" % a
)
1777 if len(add_upn
) > 0:
1778 raise CommandError("--add-upn-suffix not allowed together with DOMAIN")
1779 if len(delete_upn
) > 0:
1780 raise CommandError("--delete-upn-suffix not allowed together with DOMAIN")
1781 if len(add_spn
) > 0:
1782 raise CommandError("--add-spn-suffix not allowed together with DOMAIN")
1783 if len(delete_spn
) > 0:
1784 raise CommandError("--delete-spn-suffix not allowed together with DOMAIN")
1786 if refresh
is not None:
1787 if refresh
== "store":
1788 require_update
= True
1790 if enable_all
and refresh
!= "store":
1791 raise CommandError("--enable-all not allowed together with --refresh=%s" % refresh
)
1793 if len(enable_tln
) > 0:
1794 raise CommandError("--enable-tln not allowed together with --refresh")
1795 if len(disable_tln
) > 0:
1796 raise CommandError("--disable-tln not allowed together with --refresh")
1798 if len(add_tln_ex
) > 0:
1799 raise CommandError("--add-tln-ex not allowed together with --refresh")
1800 if len(delete_tln_ex
) > 0:
1801 raise CommandError("--delete-tln-ex not allowed together with --refresh")
1803 if len(enable_nb
) > 0:
1804 raise CommandError("--enable-nb not allowed together with --refresh")
1805 if len(disable_nb
) > 0:
1806 raise CommandError("--disable-nb not allowed together with --refresh")
1808 if len(enable_sid_str
) > 0:
1809 raise CommandError("--enable-sid not allowed together with --refresh")
1810 if len(disable_sid_str
) > 0:
1811 raise CommandError("--disable-sid not allowed together with --refresh")
1814 require_update
= True
1816 if len(enable_tln
) > 0:
1817 raise CommandError("--enable-tln not allowed together with --enable-all")
1819 if len(enable_nb
) > 0:
1820 raise CommandError("--enable-nb not allowed together with --enable-all")
1822 if len(enable_sid_str
) > 0:
1823 raise CommandError("--enable-sid not allowed together with --enable-all")
1825 if len(enable_tln
) > 0:
1826 require_update
= True
1827 if len(disable_tln
) > 0:
1828 require_update
= True
1829 for e
in enable_tln
:
1830 for d
in disable_tln
:
1831 if e
.lower() != d
.lower():
1833 raise CommandError("value[%s] specified for --enable-tln and --disable-tln" % e
)
1835 if len(add_tln_ex
) > 0:
1836 for n
in add_tln_ex
:
1837 if not n
.startswith("*."):
1839 raise CommandError("value[%s] specified for --add-tln-ex should not include with '*.'" % n
)
1840 require_update
= True
1841 if len(delete_tln_ex
) > 0:
1842 for n
in delete_tln_ex
:
1843 if not n
.startswith("*."):
1845 raise CommandError("value[%s] specified for --delete-tln-ex should not include with '*.'" % n
)
1846 require_update
= True
1847 for a
in add_tln_ex
:
1848 for d
in delete_tln_ex
:
1849 if a
.lower() != d
.lower():
1851 raise CommandError("value[%s] specified for --add-tln-ex and --delete-tln-ex" % a
)
1853 if len(enable_nb
) > 0:
1854 require_update
= True
1855 if len(disable_nb
) > 0:
1856 require_update
= True
1858 for d
in disable_nb
:
1859 if e
.upper() != d
.upper():
1861 raise CommandError("value[%s] specified for --enable-nb and --disable-nb" % e
)
1864 for s
in enable_sid_str
:
1866 sid
= security
.dom_sid(s
)
1867 except (ValueError, TypeError):
1868 raise CommandError("value[%s] specified for --enable-sid is not a valid SID" % s
)
1869 enable_sid
.append(sid
)
1871 for s
in disable_sid_str
:
1873 sid
= security
.dom_sid(s
)
1874 except (ValueError, TypeError):
1875 raise CommandError("value[%s] specified for --disable-sid is not a valid SID" % s
)
1876 disable_sid
.append(sid
)
1877 if len(enable_sid
) > 0:
1878 require_update
= True
1879 if len(disable_sid
) > 0:
1880 require_update
= True
1881 for e
in enable_sid
:
1882 for d
in disable_sid
:
1885 raise CommandError("value[%s] specified for --enable-sid and --disable-sid" % e
)
1887 local_policy_access
= lsa
.LSA_POLICY_VIEW_LOCAL_INFORMATION
1889 local_policy_access |
= lsa
.LSA_POLICY_TRUST_ADMIN
1891 local_server
= self
.setup_local_server(sambaopts
, localdcopts
)
1893 local_lsa
= self
.new_local_lsa_connection()
1894 except RuntimeError as error
:
1895 raise self
.LocalRuntimeError(self
, error
, "failed to connect lsa server")
1901 local_revision_info1
,
1903 ) = self
.get_lsa_info(local_lsa
, local_policy_access
)
1904 except RuntimeError as error
:
1905 raise self
.LocalRuntimeError(self
, error
, "failed to query LSA_POLICY_INFO_DNS")
1907 self
.outf
.write("LocalDomain Netbios[%s] DNS[%s] SID[%s]\n" % (
1908 local_lsa_info
.name
.string
,
1909 local_lsa_info
.dns_domain
.string
,
1910 local_lsa_info
.sid
))
1914 local_netlogon
= self
.new_local_netlogon_connection()
1915 except RuntimeError as error
:
1916 raise self
.LocalRuntimeError(self
, error
, "failed to connect netlogon server")
1919 local_netlogon_info
= self
.get_netlogon_dc_info(local_netlogon
, local_server
)
1920 except RuntimeError as error
:
1921 raise self
.LocalRuntimeError(self
, error
, "failed to get netlogon dc info")
1923 if local_netlogon_info
.domain_name
!= local_netlogon_info
.forest_name
:
1924 raise CommandError("The local domain [%s] is not the forest root [%s]" % (
1925 local_netlogon_info
.domain_name
,
1926 local_netlogon_info
.forest_name
))
1929 # get all information about our own forest
1930 own_forest_info
= local_netlogon
.netr_DsRGetForestTrustInformation(local_netlogon_info
.dc_unc
,
1932 except RuntimeError as error
:
1933 if self
.check_runtime_error(error
, werror
.WERR_RPC_S_PROCNUM_OUT_OF_RANGE
):
1934 raise CommandError("LOCAL_DC[%s]: netr_DsRGetForestTrustInformation() not supported." % (
1937 if self
.check_runtime_error(error
, werror
.WERR_INVALID_FUNCTION
):
1938 raise CommandError("LOCAL_DC[%s]: netr_DsRGetForestTrustInformation() not supported." % (
1941 if self
.check_runtime_error(error
, werror
.WERR_NERR_ACFNOTLOADED
):
1942 raise CommandError("LOCAL_DC[%s]: netr_DsRGetForestTrustInformation() not supported." % (
1945 raise self
.LocalRuntimeError(self
, error
, "netr_DsRGetForestTrustInformation() failed")
1947 self
.outf
.write("Own forest trust information...\n")
1948 self
.write_forest_trust_info(own_forest_info
,
1949 tln
=local_lsa_info
.dns_domain
.string
)
1952 local_samdb
= self
.new_local_ldap_connection()
1953 except RuntimeError as error
:
1954 raise self
.LocalRuntimeError(self
, error
, "failed to connect to SamDB")
1956 local_partitions_dn
= "CN=Partitions,%s" % str(local_samdb
.get_config_basedn())
1957 attrs
= ['uPNSuffixes', 'msDS-SPNSuffixes']
1959 msgs
= local_samdb
.search(base
=local_partitions_dn
,
1960 scope
=ldb
.SCOPE_BASE
,
1961 expression
="(objectClass=crossRefContainer)",
1963 stored_msg
= msgs
[0]
1964 except ldb
.LdbError
as error
:
1965 raise self
.LocalLdbError(self
, error
, "failed to search partition dn")
1967 stored_upn_vals
= []
1968 if 'uPNSuffixes' in stored_msg
:
1969 stored_upn_vals
.extend(stored_msg
['uPNSuffixes'])
1971 stored_spn_vals
= []
1972 if 'msDS-SPNSuffixes' in stored_msg
:
1973 stored_spn_vals
.extend(stored_msg
['msDS-SPNSuffixes'])
1975 self
.outf
.write("Stored uPNSuffixes attributes[%d]:\n" % len(stored_upn_vals
))
1976 for v
in stored_upn_vals
:
1977 self
.outf
.write("TLN: %-32s DNS[*.%s]\n" % ("", v
))
1978 self
.outf
.write("Stored msDS-SPNSuffixes attributes[%d]:\n" % len(stored_spn_vals
))
1979 for v
in stored_spn_vals
:
1980 self
.outf
.write("TLN: %-32s DNS[*.%s]\n" % ("", v
))
1982 if not require_update
:
1986 update_upn_vals
= []
1987 update_upn_vals
.extend(stored_upn_vals
)
1990 update_spn_vals
= []
1991 update_spn_vals
.extend(stored_spn_vals
)
1994 for v
in update_upn_vals
:
1995 if str(v
).lower() == upn
.lower():
1996 raise CommandError("Entry already present for "
1997 "value[%s] specified for "
1998 "--add-upn-suffix" % upn
)
1999 update_upn_vals
.append(upn
)
2002 for upn
in delete_upn
:
2004 for i
, v
in enumerate(update_upn_vals
):
2005 if str(v
).lower() != upn
.lower():
2010 raise CommandError("Entry not found for value[%s] specified for --delete-upn-suffix" % upn
)
2012 update_upn_vals
.pop(idx
)
2016 for v
in update_spn_vals
:
2017 if str(v
).lower() == spn
.lower():
2018 raise CommandError("Entry already present for "
2019 "value[%s] specified for "
2020 "--add-spn-suffix" % spn
)
2021 update_spn_vals
.append(spn
)
2024 for spn
in delete_spn
:
2026 for i
, v
in enumerate(update_spn_vals
):
2027 if str(v
).lower() != spn
.lower():
2032 raise CommandError("Entry not found for value[%s] specified for --delete-spn-suffix" % spn
)
2034 update_spn_vals
.pop(idx
)
2037 self
.outf
.write("Update uPNSuffixes attributes[%d]:\n" % len(update_upn_vals
))
2038 for v
in update_upn_vals
:
2039 self
.outf
.write("TLN: %-32s DNS[*.%s]\n" % ("", v
))
2040 self
.outf
.write("Update msDS-SPNSuffixes attributes[%d]:\n" % len(update_spn_vals
))
2041 for v
in update_spn_vals
:
2042 self
.outf
.write("TLN: %-32s DNS[*.%s]\n" % ("", v
))
2044 update_msg
= ldb
.Message()
2045 update_msg
.dn
= stored_msg
.dn
2048 update_msg
['uPNSuffixes'] = ldb
.MessageElement(update_upn_vals
,
2049 ldb
.FLAG_MOD_REPLACE
,
2052 update_msg
['msDS-SPNSuffixes'] = ldb
.MessageElement(update_spn_vals
,
2053 ldb
.FLAG_MOD_REPLACE
,
2056 local_samdb
.modify(update_msg
)
2057 except ldb
.LdbError
as error
:
2058 raise self
.LocalLdbError(self
, error
, "failed to update partition dn")
2061 stored_forest_info
= local_netlogon
.netr_DsRGetForestTrustInformation(local_netlogon_info
.dc_unc
,
2063 except RuntimeError as error
:
2064 raise self
.LocalRuntimeError(self
, error
, "netr_DsRGetForestTrustInformation() failed")
2066 self
.outf
.write("Stored forest trust information...\n")
2067 self
.write_forest_trust_info(stored_forest_info
,
2068 tln
=local_lsa_info
.dns_domain
.string
)
2072 lsaString
= lsa
.String()
2073 lsaString
.string
= domain
2075 local_lsa
.QueryTrustedDomainInfoByName(local_policy
,
2077 lsa
.LSA_TRUSTED_DOMAIN_INFO_INFO_EX
)
2078 except NTSTATUSError
as error
:
2079 if self
.check_runtime_error(error
, ntstatus
.NT_STATUS_OBJECT_NAME_NOT_FOUND
):
2080 raise CommandError("trusted domain object does not exist for domain [%s]" % domain
)
2082 raise self
.LocalRuntimeError(self
, error
, "QueryTrustedDomainInfoByName(INFO_EX) failed")
2084 self
.outf
.write("LocalTDO Netbios[%s] DNS[%s] SID[%s]\n" % (
2085 local_tdo_info
.netbios_name
.string
,
2086 local_tdo_info
.domain_name
.string
,
2087 local_tdo_info
.sid
))
2089 if not local_tdo_info
.trust_attributes
& lsa
.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
:
2090 raise CommandError("trusted domain object for domain [%s] is not marked as FOREST_TRANSITIVE." % domain
)
2092 if refresh
is not None:
2094 local_netlogon
= self
.new_local_netlogon_connection()
2095 except RuntimeError as error
:
2096 raise self
.LocalRuntimeError(self
, error
, "failed to connect netlogon server")
2099 local_netlogon_info
= self
.get_netlogon_dc_info(local_netlogon
, local_server
)
2100 except RuntimeError as error
:
2101 raise self
.LocalRuntimeError(self
, error
, "failed to get netlogon dc info")
2103 lsa_update_check
= 1
2104 if refresh
== "store":
2105 netlogon_update_tdo
= netlogon
.DS_GFTI_UPDATE_TDO
2107 lsa_update_check
= 0
2109 netlogon_update_tdo
= 0
2112 # get all information about the remote trust
2113 # this triggers netr_GetForestTrustInformation to the remote domain
2114 # and lsaRSetForestTrustInformation() locally, but new top level
2115 # names are disabled by default.
2116 fresh_forest_info
= \
2117 local_netlogon
.netr_DsRGetForestTrustInformation(local_netlogon_info
.dc_unc
,
2118 local_tdo_info
.domain_name
.string
,
2119 netlogon_update_tdo
)
2120 except RuntimeError as error
:
2121 raise self
.LocalRuntimeError(self
, error
, "netr_DsRGetForestTrustInformation() failed")
2124 fresh_forest_collision
= \
2125 local_lsa
.lsaRSetForestTrustInformation(local_policy
,
2126 local_tdo_info
.domain_name
,
2127 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
,
2130 except RuntimeError as error
:
2131 raise self
.LocalRuntimeError(self
, error
, "lsaRSetForestTrustInformation() failed")
2133 self
.outf
.write("Fresh forest trust information...\n")
2134 self
.write_forest_trust_info(fresh_forest_info
,
2135 tln
=local_tdo_info
.domain_name
.string
,
2136 collisions
=fresh_forest_collision
)
2138 if refresh
== "store":
2140 lsaString
= lsa
.String()
2141 lsaString
.string
= local_tdo_info
.domain_name
.string
2142 stored_forest_info
= \
2143 local_lsa
.lsaRQueryForestTrustInformation(local_policy
,
2145 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
)
2146 except RuntimeError as error
:
2147 raise self
.LocalRuntimeError(self
, error
, "lsaRQueryForestTrustInformation() failed")
2149 self
.outf
.write("Stored forest trust information...\n")
2150 self
.write_forest_trust_info(stored_forest_info
,
2151 tln
=local_tdo_info
.domain_name
.string
)
2156 # The none --refresh path
2160 lsaString
= lsa
.String()
2161 lsaString
.string
= local_tdo_info
.domain_name
.string
2162 local_forest_info
= \
2163 local_lsa
.lsaRQueryForestTrustInformation(local_policy
,
2165 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
)
2166 except RuntimeError as error
:
2167 raise self
.LocalRuntimeError(self
, error
, "lsaRQueryForestTrustInformation() failed")
2169 self
.outf
.write("Local forest trust information...\n")
2170 self
.write_forest_trust_info(local_forest_info
,
2171 tln
=local_tdo_info
.domain_name
.string
)
2173 if not require_update
:
2177 entries
.extend(local_forest_info
.entries
)
2178 update_forest_info
= lsa
.ForestTrustInformation()
2179 update_forest_info
.count
= len(entries
)
2180 update_forest_info
.entries
= entries
2183 for r
in update_forest_info
.entries
:
2184 if r
.type != lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
2189 r
.flags
&= ~lsa
.LSA_TLN_DISABLED_MASK
2190 for r
in update_forest_info
.entries
:
2191 if r
.type != lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
:
2196 r
.flags
&= ~lsa
.LSA_NB_DISABLED_MASK
2197 r
.flags
&= ~lsa
.LSA_SID_DISABLED_MASK
2199 for tln
in enable_tln
:
2201 for i
, r
in enumerate(update_forest_info
.entries
):
2202 if r
.type != lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
2204 if r
.forest_trust_data
.string
.lower() != tln
.lower():
2209 raise CommandError("Entry not found for value[%s] specified for --enable-tln" % tln
)
2210 if not update_forest_info
.entries
[idx
].flags
& lsa
.LSA_TLN_DISABLED_MASK
:
2211 raise CommandError("Entry found for value[%s] specified for --enable-tln is already enabled" % tln
)
2212 update_forest_info
.entries
[idx
].time
= 0
2213 update_forest_info
.entries
[idx
].flags
&= ~lsa
.LSA_TLN_DISABLED_MASK
2215 for tln
in disable_tln
:
2217 for i
, r
in enumerate(update_forest_info
.entries
):
2218 if r
.type != lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
2220 if r
.forest_trust_data
.string
.lower() != tln
.lower():
2225 raise CommandError("Entry not found for value[%s] specified for --disable-tln" % tln
)
2226 if update_forest_info
.entries
[idx
].flags
& lsa
.LSA_TLN_DISABLED_ADMIN
:
2227 raise CommandError("Entry found for value[%s] specified for --disable-tln is already disabled" % tln
)
2228 update_forest_info
.entries
[idx
].time
= 0
2229 update_forest_info
.entries
[idx
].flags
&= ~lsa
.LSA_TLN_DISABLED_MASK
2230 update_forest_info
.entries
[idx
].flags |
= lsa
.LSA_TLN_DISABLED_ADMIN
2232 for tln_ex
in add_tln_ex
:
2234 for i
, r
in enumerate(update_forest_info
.entries
):
2235 if r
.type != lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
2237 if r
.forest_trust_data
.string
.lower() != tln_ex
.lower():
2242 raise CommandError("Entry already present for value[%s] specified for --add-tln-ex" % tln_ex
)
2244 tln_dot
= ".%s" % tln_ex
.lower()
2246 for i
, r
in enumerate(update_forest_info
.entries
):
2247 if r
.type != lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
2249 r_dot
= ".%s" % r
.forest_trust_data
.string
.lower()
2250 if tln_dot
== r_dot
:
2251 raise CommandError("TLN entry present for value[%s] specified for --add-tln-ex" % tln_ex
)
2252 if not tln_dot
.endswith(r_dot
):
2258 raise CommandError("No TLN parent present for value[%s] specified for --add-tln-ex" % tln_ex
)
2260 r
= lsa
.ForestTrustRecord()
2261 r
.type = lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
2264 r
.forest_trust_data
.string
= tln_ex
2267 entries
.extend(update_forest_info
.entries
)
2268 entries
.insert(idx
+ 1, r
)
2269 update_forest_info
.count
= len(entries
)
2270 update_forest_info
.entries
= entries
2272 for tln_ex
in delete_tln_ex
:
2274 for i
, r
in enumerate(update_forest_info
.entries
):
2275 if r
.type != lsa
.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
2277 if r
.forest_trust_data
.string
.lower() != tln_ex
.lower():
2282 raise CommandError("Entry not found for value[%s] specified for --delete-tln-ex" % tln_ex
)
2285 entries
.extend(update_forest_info
.entries
)
2287 update_forest_info
.count
= len(entries
)
2288 update_forest_info
.entries
= entries
2290 for nb
in enable_nb
:
2292 for i
, r
in enumerate(update_forest_info
.entries
):
2293 if r
.type != lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
:
2295 if r
.forest_trust_data
.netbios_domain_name
.string
.upper() != nb
.upper():
2300 raise CommandError("Entry not found for value[%s] specified for --enable-nb" % nb
)
2301 if not update_forest_info
.entries
[idx
].flags
& lsa
.LSA_NB_DISABLED_MASK
:
2302 raise CommandError("Entry found for value[%s] specified for --enable-nb is already enabled" % nb
)
2303 update_forest_info
.entries
[idx
].time
= 0
2304 update_forest_info
.entries
[idx
].flags
&= ~lsa
.LSA_NB_DISABLED_MASK
2306 for nb
in disable_nb
:
2308 for i
, r
in enumerate(update_forest_info
.entries
):
2309 if r
.type != lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
:
2311 if r
.forest_trust_data
.netbios_domain_name
.string
.upper() != nb
.upper():
2316 raise CommandError("Entry not found for value[%s] specified for --delete-nb" % nb
)
2317 if update_forest_info
.entries
[idx
].flags
& lsa
.LSA_NB_DISABLED_ADMIN
:
2318 raise CommandError("Entry found for value[%s] specified for --disable-nb is already disabled" % nb
)
2319 update_forest_info
.entries
[idx
].time
= 0
2320 update_forest_info
.entries
[idx
].flags
&= ~lsa
.LSA_NB_DISABLED_MASK
2321 update_forest_info
.entries
[idx
].flags |
= lsa
.LSA_NB_DISABLED_ADMIN
2323 for sid
in enable_sid
:
2325 for i
, r
in enumerate(update_forest_info
.entries
):
2326 if r
.type != lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
:
2328 if r
.forest_trust_data
.domain_sid
!= sid
:
2333 raise CommandError("Entry not found for value[%s] specified for --enable-sid" % sid
)
2334 if not update_forest_info
.entries
[idx
].flags
& lsa
.LSA_SID_DISABLED_MASK
:
2335 raise CommandError("Entry found for value[%s] specified for --enable-sid is already enabled" % nb
)
2336 update_forest_info
.entries
[idx
].time
= 0
2337 update_forest_info
.entries
[idx
].flags
&= ~lsa
.LSA_SID_DISABLED_MASK
2339 for sid
in disable_sid
:
2341 for i
, r
in enumerate(update_forest_info
.entries
):
2342 if r
.type != lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
:
2344 if r
.forest_trust_data
.domain_sid
!= sid
:
2349 raise CommandError("Entry not found for value[%s] specified for --delete-sid" % sid
)
2350 if update_forest_info
.entries
[idx
].flags
& lsa
.LSA_SID_DISABLED_ADMIN
:
2351 raise CommandError("Entry found for value[%s] specified for --disable-sid is already disabled" % nb
)
2352 update_forest_info
.entries
[idx
].time
= 0
2353 update_forest_info
.entries
[idx
].flags
&= ~lsa
.LSA_SID_DISABLED_MASK
2354 update_forest_info
.entries
[idx
].flags |
= lsa
.LSA_SID_DISABLED_ADMIN
2357 update_forest_collision
= local_lsa
.lsaRSetForestTrustInformation(local_policy
,
2358 local_tdo_info
.domain_name
,
2359 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
,
2360 update_forest_info
, 0)
2361 except RuntimeError as error
:
2362 raise self
.LocalRuntimeError(self
, error
, "lsaRSetForestTrustInformation() failed")
2364 self
.outf
.write("Updated forest trust information...\n")
2365 self
.write_forest_trust_info(update_forest_info
,
2366 tln
=local_tdo_info
.domain_name
.string
,
2367 collisions
=update_forest_collision
)
2370 lsaString
= lsa
.String()
2371 lsaString
.string
= local_tdo_info
.domain_name
.string
2372 stored_forest_info
= local_lsa
.lsaRQueryForestTrustInformation(local_policy
,
2374 lsa
.LSA_FOREST_TRUST_DOMAIN_INFO
)
2375 except RuntimeError as error
:
2376 raise self
.LocalRuntimeError(self
, error
, "lsaRQueryForestTrustInformation() failed")
2378 self
.outf
.write("Stored forest trust information...\n")
2379 self
.write_forest_trust_info(stored_forest_info
,
2380 tln
=local_tdo_info
.domain_name
.string
)
2384 class cmd_domain_trust(SuperCommand
):
2385 """Domain and forest trust management."""
2388 subcommands
["list"] = cmd_domain_trust_list()
2389 subcommands
["show"] = cmd_domain_trust_show()
2390 subcommands
["create"] = cmd_domain_trust_create()
2391 subcommands
["modify"] = cmd_domain_trust_modify()
2392 subcommands
["delete"] = cmd_domain_trust_delete()
2393 subcommands
["validate"] = cmd_domain_trust_validate()
2394 subcommands
["namespaces"] = cmd_domain_trust_namespaces()