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
,
27 from samba
.ntstatus
import (
28 NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
30 from samba
import crypto
31 from secrets
import token_bytes
34 def OpenPolicyFallback(
38 in_revision_info
: lsa
.revision_info1
,
39 sec_qos
: bool = False,
42 attr
= lsa
.ObjectAttribute()
46 qos
.impersonation_level
= 2
48 qos
.effective_only
= 0
53 out_version
, out_rev_info
, policy
= conn
.OpenPolicy3(
60 except NTSTATUSError
as e
:
61 if e
.args
[0] == NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
:
63 out_rev_info
= lsa
.revision_info1()
64 out_rev_info
.revision
= 1
65 out_rev_info
.supported_features
= 0
67 policy
= conn
.OpenPolicy2(system_name
, attr
, access_mask
)
71 return out_version
, out_rev_info
, policy
74 def CreateTrustedDomainRelax(
76 policy
: misc
.policy_handle
,
77 trust_info
: lsa
.TrustDomainInfoInfoEx
,
79 in_blob
: drsblobs
.trustAuthInOutBlob
,
80 out_blob
: drsblobs
.trustAuthInOutBlob
83 def generate_AuthInfoInternal(session_key
, incoming
=None, outgoing
=None):
84 confounder
= string_to_byte_array(token_bytes(512))
86 trustpass
= drsblobs
.trustDomainPasswords()
88 trustpass
.confounder
= confounder
89 trustpass
.outgoing
= outgoing
90 trustpass
.incoming
= incoming
92 trustpass_blob
= ndr_pack(trustpass
)
94 encrypted_trustpass
= arcfour_encrypt(session_key
, trustpass_blob
)
96 auth_blob
= lsa
.DATA_BUF2()
97 auth_blob
.size
= len(encrypted_trustpass
)
98 auth_blob
.data
= string_to_byte_array(encrypted_trustpass
)
100 auth_info
= lsa
.TrustDomainInfoAuthInfoInternal()
101 auth_info
.auth_blob
= auth_blob
105 session_key
= lsaconn
.session_key
108 if lsaconn
.transport_encrypted():
109 crypto
.set_relax_mode()
110 auth_info
= generate_AuthInfoInternal(session_key
,
114 crypto
.set_strict_mode()
116 return lsaconn
.CreateTrustedDomainEx2(policy
, trust_info
, auth_info
, mask
)
119 def CreateTrustedDomainFallback(
121 policy_handle
: misc
.policy_handle
,
122 trust_info
: lsa
.TrustDomainInfoInfoEx
,
125 srv_revision_info1
: lsa
.revision_info1
,
126 in_blob
: drsblobs
.trustAuthInOutBlob
,
127 out_blob
: drsblobs
.trustAuthInOutBlob
129 def generate_AuthInfoInternalAES(
134 trustpass
= drsblobs
.trustDomainPasswords()
136 trustpass
.outgoing
= outgoing
137 trustpass
.incoming
= incoming
139 trustpass_blob
= ndr_pack(trustpass
)
141 lsa_aes256_enc_key
= (
142 "Microsoft LSAD encryption key AEAD-AES-256-CBC-HMAC-SHA512 16".encode()
145 lsa_aes256_mac_key
= (
146 "Microsoft LSAD MAC key AEAD-AES-256-CBC-HMAC-SHA512 16".encode()
151 ciphertext
, auth_data
= aead_aes_256_cbc_hmac_sha512(
159 return ciphertext
, iv
, auth_data
162 and srv_revision_info1
.revision
== 1
163 and (srv_revision_info1
.supported_features
164 & lsa
.LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER
)):
166 ciphertext
, iv
, auth_data
= generate_AuthInfoInternalAES(
167 conn
.session_key
, in_blob
, out_blob
170 auth_blob
= lsa
.DATA_BUF2()
171 auth_blob
.size
= len(ciphertext
)
172 auth_blob
.data
= string_to_byte_array(ciphertext
)
174 auth_info
= lsa
.TrustDomainInfoAuthInfoInternalAES()
175 auth_info
.cipher
= auth_blob
176 auth_info
.salt
= string_to_byte_array(iv
)
177 auth_info
.auth_data
= string_to_byte_array(auth_data
)
179 return conn
.CreateTrustedDomainEx3(
186 return CreateTrustedDomainRelax(