Skip to content

Commit

Permalink
Better handling of clients' closing connections in ntlmrelayx LDAP socks
Browse files Browse the repository at this point in the history
  • Loading branch information
b1two committed Dec 18, 2024
1 parent dedaa9b commit 2771660
Showing 1 changed file with 17 additions and 18 deletions.
35 changes: 17 additions & 18 deletions impacket/examples/ntlmrelayx/servers/socksplugins/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ def skipAuthentication(self):
# Faking an NTLM authentication with the client
while True:
messages = self.recv_ldap_msg()
LOG.debug(f'Received {len(messages)} message(s)')
if messages is None:
LOG.warning('LDAP: Client did not send ldap messages or closed connection')
return False
LOG.debug(f'LDAP: Received {len(messages)} message(s)')

for message in messages:
msg_component = message['protocolOp'].getComponent()
Expand All @@ -43,7 +46,7 @@ def skipAuthentication(self):
# First bind message without authentication
# Replying with a request for NTLM authentication

LOG.debug('Got empty bind request')
LOG.debug('LDAP: Got empty bind request')

bindresponse = BindResponse()
bindresponse['resultCode'] = ResultCode('success')
Expand All @@ -57,7 +60,7 @@ def skipAuthentication(self):
elif 'sicilyNegotiate' in msg_component['authentication']:
# Requested NTLM authentication

LOG.debug('Got NTLM bind request')
LOG.debug('LDAP: Got NTLM bind request')

# Load negotiate message
negotiateMessage = ntlm.NTLMAuthNegotiate()
Expand Down Expand Up @@ -184,6 +187,9 @@ def recv_ldap_msg(self):
done = False
while not done:
recvData = self.socksSocket.recv(self.MSG_SIZE)
if recvData == b'':
# Connection got closed
return None
if len(recvData) < self.MSG_SIZE:
done = True
data += recvData
Expand All @@ -194,19 +200,12 @@ def recv_ldap_msg(self):
message, remaining = decoder.decode(data, asn1Spec=LDAPMessage())
except SubstrateUnderrunError:
# We need more data
remaining = data + self.socksSocket.recv(self.MSG_SIZE)
new_data = self.socksSocket.recv(self.MSG_SIZE)
if new_data == b'':
# Connection got closed
return None
remaining = data + new_data
else:
if message['messageID'] == 0: # unsolicited notification
name = message['protocolOp']['extendedResp']['responseName'] or message['responseName']
notification = KNOWN_NOTIFICATIONS.get(name, "Unsolicited Notification '%s'" % name)
if name == NOTIFICATION_DISCONNECT: # Server has disconnected
self.close()
raise LDAPSessionError(
error=int(message['protocolOp']['extendedResp']['resultCode']),
errorString='%s -> %s: %s' % (notification,
message['protocolOp']['extendedResp']['resultCode'].prettyPrint(),
message['protocolOp']['extendedResp']['diagnosticMessage'])
)
response.append(message)
data = remaining

Expand Down Expand Up @@ -278,7 +277,7 @@ def tunnelConnection(self):
# Free the relay so that it can be reused
self.activeRelays[self.username]['inUse'] = False

LOG.debug('Finished tunnelling')
LOG.debug('LDAP: Finished tunnelling')

return True

Expand All @@ -289,7 +288,7 @@ def is_forwardable_request(self, data):

# Search for unbind requests
if msg_component.isSameTypeWith(UnbindRequest):
LOG.warning('Client tried to unbind LDAP connection, skipping message')
LOG.warning('LDAP: Client tried to unbind LDAP connection, skipping message')
return False
except Exception:
# Is probably not an unbind LDAP message
Expand All @@ -305,7 +304,7 @@ def is_allowed_request(self, data):
# Search for START_TLS LDAP extendedReq OID
if msg_component.isSameTypeWith(ExtendedRequest) and msg_component['requestName'].asOctets() == b'1.3.6.1.4.1.1466.20037':
# 1.3.6.1.4.1.1466.20037 is LDAP_START_TLS_OID
LOG.warning('Client tried to initiate Start TLS, closing connection')
LOG.warning('LDAP: Client tried to initiate Start TLS, closing connection')
return False
except Exception:
# Is probably not a ExtendedReq message
Expand Down

0 comments on commit 2771660

Please sign in to comment.