-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Skelsec
committed
May 18, 2023
1 parent
0bdf96b
commit 51c7bd0
Showing
8 changed files
with
361 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
from asysocks.unicomm.common.target import UniTarget, UniProto | ||
from asysocks.unicomm.server import UniServer | ||
from msldap.network.packetizer import LDAPPacketizer | ||
from msldap.relay.serverconnection import LDAPRelayServerConnection | ||
from asyauth.protocols.spnego.relay.native import spnegorelay_ntlm_factory | ||
from asyauth.protocols.ntlm.relay.native import NTLMRelaySettings, ntlmrelay_factory | ||
import traceback | ||
import asyncio | ||
|
||
class LDAPServerSettings: | ||
def __init__(self, gssapi_factory): | ||
self.gssapi_factory = gssapi_factory | ||
|
||
@property | ||
def gssapi(self): | ||
return self.gssapi_factory() | ||
|
||
class LDAPRelayServer: | ||
def __init__(self, target, settings): | ||
self.target = target | ||
self.settings = settings | ||
self.server = None | ||
self.serving_task = None | ||
self.connections = {} | ||
self.conn_ctr = 0 | ||
|
||
def get_ctr(self): | ||
self.conn_ctr += 1 | ||
return self.conn_ctr | ||
|
||
async def __handle_connection(self): | ||
try: | ||
async for connection in self.server.serve(): | ||
print('connection in!') | ||
|
||
smbconnection = LDAPRelayServerConnection(self.settings, connection) | ||
self.connections[self.get_ctr()] = smbconnection | ||
x = asyncio.create_task(smbconnection.run()) | ||
|
||
except Exception as e: | ||
traceback.print_exc() | ||
return | ||
|
||
async def run(self): | ||
self.server = UniServer(self.target, LDAPPacketizer()) | ||
self.serving_task = asyncio.create_task(self.__handle_connection()) | ||
return self.serving_task | ||
|
||
async def test_relay_queue(rq): | ||
try: | ||
from aiosmb.connection import SMBConnection | ||
from aiosmb.commons.connection.target import SMBTarget | ||
from aiosmb.commons.interfaces.machine import SMBMachine | ||
test_target = SMBTarget('10.10.10.2') | ||
while True: | ||
item = await rq.get() | ||
print(item) | ||
connection = SMBConnection(item, test_target, preserve_gssapi=False, nosign=True) | ||
_, err = await connection.login() | ||
if err is not None: | ||
print('SMB client login err: %s' % err) | ||
print(traceback.format_tb(err.__traceback__)) | ||
continue | ||
machine = SMBMachine(connection) | ||
async for share, err in machine.list_shares(): | ||
if err is not None: | ||
print('SMB client list_shares err: %s' % err) | ||
continue | ||
print(share) | ||
|
||
except Exception as e: | ||
traceback.print_exc() | ||
return | ||
|
||
async def amain(): | ||
try: | ||
auth_relay_queue = asyncio.Queue() | ||
x = asyncio.create_task(test_relay_queue(auth_relay_queue)) | ||
target = UniTarget('0.0.0.0', 636, UniProto.SERVER_SSL_TCP) | ||
|
||
settings = LDAPServerSettings(lambda: spnegorelay_ntlm_factory(auth_relay_queue, lambda: ntlmrelay_factory())) | ||
server = LDAPRelayServer(target, settings) | ||
server_task = await server.run() | ||
await server_task | ||
except Exception as e: | ||
traceback.print_exc() | ||
return | ||
if __name__ == '__main__': | ||
asyncio.run(amain()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
from msldap.protocol.utils import calcualte_length | ||
from msldap.protocol.messages import LDAPMessage, AuthenticationChoice, protocolOp, BindResponse | ||
from msldap import logger | ||
import traceback | ||
import asyncio | ||
|
||
class LDAPRelayServerConnection: | ||
def __init__(self, settings, connection): | ||
self.settings = settings | ||
self.gssapi = settings.gssapi | ||
self.ntlm = self.gssapi.authentication_contexts['NTLMSSP - Microsoft NTLM Security Support Provider'] | ||
self.connection = connection | ||
self.__auth_type = None | ||
self.__auth_iter = 0 | ||
|
||
async def log_async(self, level, msg): | ||
if self.settings.log_q is not None: | ||
src = 'LDAPCON-%s:%s' % (self.client_ip, self.client_port) | ||
await self.settings.log_q.put((src, level, msg)) | ||
else: | ||
logger.log(level, msg) | ||
|
||
async def terminate(self): | ||
self.handle_in_task.cancel() | ||
|
||
async def __handle_ldap_in(self): | ||
async for msg_data in self.connection.read(): | ||
try: | ||
msg = LDAPMessage.load(msg_data) | ||
if msg['protocolOp']._choice == 0: | ||
await self.__bindreq(msg) | ||
else: | ||
raise Exception('Unknown LDAP message! %s' % msg.native) | ||
|
||
except Exception as e: | ||
await self.log_async(1, str(e)) | ||
return | ||
|
||
async def __bindreq(self, msg): | ||
try: | ||
msg_id = msg.native['messageID'] | ||
authdata_raw = msg.native['protocolOp']['authentication'] | ||
if isinstance(authdata_raw, bytes) is True: | ||
self.__auth_type = 'NTLM' | ||
if self.__auth_iter == 0: | ||
t = { | ||
'resultCode' : 0, | ||
'matchedDN' : 'NTLM'.encode(), | ||
'diagnosticMessage' : b'', | ||
} | ||
po = {'bindResponse' : BindResponse(t)} | ||
b= { | ||
'messageID' : msg_id, | ||
'protocolOp' : protocolOp(po), | ||
} | ||
resp = LDAPMessage(b) | ||
await self.connection.write(resp.dump()) | ||
self.__auth_iter += 1 | ||
return | ||
|
||
else: | ||
resdata, to_conitnue, err = await self.ntlm.authenticate_relay_server(authdata_raw) | ||
if err is not None: | ||
raise err | ||
|
||
if resdata is None: | ||
t = { | ||
'resultCode' : 49, | ||
'matchedDN' : b'', | ||
'diagnosticMessage' : b'8009030C: LdapErr: DSID-0C090569, comment: AcceptSecurityContext error, data 52e, v4563\x00', | ||
} | ||
po = {'bindResponse' : BindResponse(t)} | ||
b= { | ||
'messageID' : msg_id, | ||
'protocolOp' : protocolOp(po), | ||
} | ||
resp = LDAPMessage(b) | ||
|
||
await self.connection.write(resp.dump()) | ||
|
||
await self.terminate() | ||
return | ||
|
||
t = { | ||
'resultCode' : 0, | ||
'matchedDN' : resdata, | ||
'diagnosticMessage' : b'', | ||
} | ||
po = {'bindResponse' : BindResponse(t)} | ||
b= { | ||
'messageID' : msg_id, | ||
'protocolOp' : protocolOp(po), | ||
} | ||
resp = LDAPMessage(b) | ||
await self.connection.write(resp.dump()) | ||
self.__auth_iter += 1 | ||
return | ||
|
||
if isinstance(authdata_raw, dict) is True: | ||
self.__auth_type = 'GSSAPI' | ||
resdata, to_conitnue, err = await self.gssapi.authenticate_relay_server(authdata_raw['credentials']) | ||
if err is not None: | ||
raise err | ||
|
||
if resdata is None: | ||
t = { | ||
'resultCode' : 49, | ||
'matchedDN' : b'', | ||
'diagnosticMessage' : b'8009030C: LdapErr: DSID-0C090569, comment: AcceptSecurityContext error, data 52e, v4563\x00', | ||
} | ||
po = {'bindResponse' : BindResponse(t)} | ||
b= { | ||
'messageID' : msg_id, | ||
'protocolOp' : protocolOp(po), | ||
} | ||
resp = LDAPMessage(b) | ||
|
||
await self.connection.write(resp.dump()) | ||
|
||
await self.terminate() | ||
return | ||
|
||
t = { | ||
'resultCode' : 14, | ||
'matchedDN' : b'', | ||
'diagnosticMessage' : b'', | ||
'serverSaslCreds': resdata | ||
} | ||
po = {'bindResponse' : BindResponse(t)} | ||
b= { | ||
'messageID' : msg_id, | ||
'protocolOp' : protocolOp(po), | ||
} | ||
resp = LDAPMessage(b) | ||
await self.connection.write(resp.dump()) | ||
self.__auth_iter += 1 | ||
|
||
else: | ||
raise Exception('Unknown auth method %s' % authdata_raw) | ||
|
||
|
||
except Exception as e: | ||
traceback.print_exc() | ||
return | ||
|
||
async def run(self): | ||
self.handle_in_task = asyncio.create_task(self.__handle_ldap_in()) | ||
await self.handle_in_task |
Oops, something went wrong.