3 # Copyright Isaac Boukris 2020
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 from samba
.dcerpc
import lsa
, drsblobs
, misc
20 from samba
.ndr
import ndr_pack
23 aead_aes_256_cbc_hmac_sha512
,
26 from samba
.ntstatus
import (
27 NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
29 from samba
import crypto
30 from secrets
import token_bytes
33 def OpenPolicyFallback(
37 in_revision_info
: lsa
.revision_info1
,
38 sec_qos
: bool = False,
41 attr
= lsa
.ObjectAttribute()
45 qos
.impersonation_level
= 2
47 qos
.effective_only
= 0
52 out_version
, out_rev_info
, policy
= conn
.OpenPolicy3(
59 except NTSTATUSError
as e
:
60 if e
.args
[0] == NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
:
62 out_rev_info
= lsa
.revision_info1()
63 out_rev_info
.revision
= 1
64 out_rev_info
.supported_features
= 0
66 policy
= conn
.OpenPolicy2(system_name
, attr
, access_mask
)
70 return out_version
, out_rev_info
, policy
73 def CreateTrustedDomainRelax(
75 policy
: misc
.policy_handle
,
76 trust_info
: lsa
.TrustDomainInfoInfoEx
,
78 in_blob
: drsblobs
.trustAuthInOutBlob
,
79 out_blob
: drsblobs
.trustAuthInOutBlob
82 def generate_AuthInfoInternal(session_key
, incoming
=None, outgoing
=None):
83 confounder
= list(token_bytes(512))
85 trustpass
= drsblobs
.trustDomainPasswords()
87 trustpass
.confounder
= confounder
88 trustpass
.outgoing
= outgoing
89 trustpass
.incoming
= incoming
91 trustpass_blob
= ndr_pack(trustpass
)
93 encrypted_trustpass
= arcfour_encrypt(session_key
, trustpass_blob
)
95 auth_blob
= lsa
.DATA_BUF2()
96 auth_blob
.size
= len(encrypted_trustpass
)
97 auth_blob
.data
= list(encrypted_trustpass
)
99 auth_info
= lsa
.TrustDomainInfoAuthInfoInternal()
100 auth_info
.auth_blob
= auth_blob
104 session_key
= lsaconn
.session_key
107 if lsaconn
.transport_encrypted():
108 crypto
.set_relax_mode()
109 auth_info
= generate_AuthInfoInternal(session_key
,
113 crypto
.set_strict_mode()
115 return lsaconn
.CreateTrustedDomainEx2(policy
, trust_info
, auth_info
, mask
)
118 def CreateTrustedDomainFallback(
120 policy_handle
: misc
.policy_handle
,
121 trust_info
: lsa
.TrustDomainInfoInfoEx
,
124 srv_revision_info1
: lsa
.revision_info1
,
125 in_blob
: drsblobs
.trustAuthInOutBlob
,
126 out_blob
: drsblobs
.trustAuthInOutBlob
128 def generate_AuthInfoInternalAES(
133 trustpass
= drsblobs
.trustDomainPasswords()
135 trustpass
.outgoing
= outgoing
136 trustpass
.incoming
= incoming
138 trustpass_blob
= ndr_pack(trustpass
)
140 lsa_aes256_enc_key
= (
141 "Microsoft LSAD encryption key AEAD-AES-256-CBC-HMAC-SHA512 16".encode()
144 lsa_aes256_mac_key
= (
145 "Microsoft LSAD MAC key AEAD-AES-256-CBC-HMAC-SHA512 16".encode()
150 ciphertext
, auth_data
= aead_aes_256_cbc_hmac_sha512(
158 return ciphertext
, iv
, auth_data
161 and srv_revision_info1
.revision
== 1
162 and (srv_revision_info1
.supported_features
163 & lsa
.LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER
)):
165 ciphertext
, iv
, auth_data
= generate_AuthInfoInternalAES(
166 conn
.session_key
, in_blob
, out_blob
169 auth_blob
= lsa
.DATA_BUF2()
170 auth_blob
.size
= len(ciphertext
)
171 auth_blob
.data
= list(ciphertext
)
173 auth_info
= lsa
.TrustDomainInfoAuthInfoInternalAES()
174 auth_info
.cipher
= auth_blob
175 auth_info
.salt
= list(iv
)
176 auth_info
.auth_data
= list(auth_data
)
178 return conn
.CreateTrustedDomainEx3(
185 return CreateTrustedDomainRelax(