start spneg

This commit is contained in:
speyrefitte
2015-02-19 18:26:50 +01:00
parent d6428430eb
commit d6bb21565d
8 changed files with 128 additions and 23 deletions

View File

@@ -115,7 +115,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
self._nego = security == "nego" self._nego = security == "nego"
self._recodedPath = recodedPath self._recodedPath = recodedPath
if self._nego: if self._nego:
self._security = "ssl" self._security = "nla"
else: else:
self._security = security self._security = security
self._w = None self._w = None

View File

View File

@@ -23,7 +23,8 @@
""" """
from pyasn1.type import namedtype, univ from pyasn1.type import namedtype, univ
from pyasn1.codec.ber import decoder from pyasn1.codec.ber import encoder
from rdpy.core.type import Stream
class NegoData(univ.SequenceOf): class NegoData(univ.SequenceOf):
""" """
@@ -90,3 +91,25 @@ class TSSmartCardCreds(univ.Sequence):
namedtype.OptionalNamedType('userHint', univ.OctetString()), namedtype.OptionalNamedType('userHint', univ.OctetString()),
namedtype.OptionalNamedType('domainHint', univ.OctetString()) namedtype.OptionalNamedType('domainHint', univ.OctetString())
) )
def createBERRequest(negoTokens):
"""
@summary: create TSRequest from list of Type
@param negoTokens: {list(Type)}
@return: {str}
"""
negoData = NegoData()
#fill nego data tokens
i = 0
for negoToken in negoTokens:
s = Stream()
s.writeType(negoToken)
negoData.setComponentByPosition(i, s.getvalue())
i += 1
request = TSRequest()
request.setComponentByName("version", univ.Integer(2))
request.setComponentByName("negoTokens", negoData)
return encoder.encode(request)

View File

@@ -48,15 +48,42 @@ class NTLMRevision(object):
""" """
NTLMSSP_REVISION_W2K3 = 0x0F NTLMSSP_REVISION_W2K3 = 0x0F
class Negotiate(object):
"""
@see: https://msdn.microsoft.com/en-us/library/cc236650.aspx
"""
NTLMSSP_NEGOTIATE_56 = 0x80000000
NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000
NTLMSSP_NEGOTIATE_128 = 0x20000000
NTLMSSP_NEGOTIATE_VERSION = 0x02000000
NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000
NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000
NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000
NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000
NTLMSSP_TARGET_TYPE_SERVER = 0x00020000
NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000
NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000
NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000
NTLMSSP_NEGOTIATE_NTLM = 0x00000200
NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080
NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040
NTLMSSP_NEGOTIATE_SEAL = 0x00000020
NTLMSSP_NEGOTIATE_SIGN = 0x00000010
NTLMSSP_REQUEST_TARGET = 0x00000004
NTLM_NEGOTIATE_OEM = 0x00000002
NTLMSSP_NEGOTIATE_UNICODE = 0x00000001
class Version(CompositeType): class Version(CompositeType):
""" """
@summary: Version structure as describe in NTLM spec @summary: Version structure as describe in NTLM spec
@see: https://msdn.microsoft.com/en-us/library/cc236654.aspx @see: https://msdn.microsoft.com/en-us/library/cc236654.aspx
""" """
def __init__(self): def __init__(self, conditional):
CompositeType.__init__(self, conditional = conditional)
self.ProductMajorVersion = UInt8(MajorVersion.WINDOWS_MAJOR_VERSION_6) self.ProductMajorVersion = UInt8(MajorVersion.WINDOWS_MAJOR_VERSION_6)
self.ProductMinorVersion = UInt8(MinorVersion.WINDOWS_MINOR_VERSION_2) self.ProductMinorVersion = UInt8(MinorVersion.WINDOWS_MINOR_VERSION_0)
self.ProductBuild = UInt16Le() self.ProductBuild = UInt16Le(6002)
self.Reserved = UInt24Le() self.Reserved = UInt24Le()
self.NTLMRevisionCurrent = UInt8(NTLMRevision.NTLMSSP_REVISION_W2K3) self.NTLMRevisionCurrent = UInt8(NTLMRevision.NTLMSSP_REVISION_W2K3)
@@ -69,13 +96,21 @@ class NegotiateMessage(CompositeType):
CompositeType.__init__(self) CompositeType.__init__(self)
self.Signature = String("NTLMSSP\x00", constant = True) self.Signature = String("NTLMSSP\x00", constant = True)
self.MessageType = UInt32Le(0x00000001) self.MessageType = UInt32Le(0x00000001)
self.NegotiateFlags = UInt32Le() self.NegotiateFlags = UInt32Le(Negotiate.NTLMSSP_NEGOTIATE_KEY_EXCH |
Negotiate.NTLMSSP_NEGOTIATE_128 |
Negotiate.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY |
Negotiate.NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
Negotiate.NTLMSSP_NEGOTIATE_NTLM |
Negotiate.NTLMSSP_NEGOTIATE_SIGN |
Negotiate.NTLMSSP_NEGOTIATE_SEAL |
Negotiate.NTLMSSP_REQUEST_TARGET |
Negotiate.NTLMSSP_NEGOTIATE_UNICODE)
self.DomainNameLen = UInt16Le() self.DomainNameLen = UInt16Le()
self.DomainNameMaxLen = UInt16Le(self.DomainNameLen) self.DomainNameMaxLen = UInt16Le(lambda:self.DomainNameLen.value)
self.DomainNameBufferOffset = UInt32Le() self.DomainNameBufferOffset = UInt32Le()
self.WorkstationLen = UInt16Le() self.WorkstationLen = UInt16Le()
self.WorkstationMaxLen = UInt16Le(self.WorkstationLen) self.WorkstationMaxLen = UInt16Le(lambda:self.WorkstationLen.value)
self.WorkstationBufferOffset = UInt32Le() self.WorkstationBufferOffset = UInt32Le()
self.Version = Version() self.Version = Version(conditional = lambda:(self.NegotiateFlags & Negotiate.NTLMSSP_NEGOTIATE_VERSION))
self.Payload = String() self.Payload = String()

View File

@@ -0,0 +1,38 @@
#
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
# rdpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
@summary: Simple and protected GSS-API Negotiation Mechanism
@see: https://msdn.microsoft.com/en-us/library/cc247021.aspx
"""
from pyasn1.type import namedtype, univ
class NegTokenInit2(univ.Sequence):
"""
@summary: main structure
@see: https://msdn.microsoft.com/en-us/library/cc247039.aspx
"""
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('mechTypes', univ.Integer()),
namedtype.OptionalNamedType('reqFlags', NegoData()),
namedtype.OptionalNamedType('mechToken', univ.OctetString()),
namedtype.OptionalNamedType('negHints', univ.OctetString()),
namedtype.OptionalNamedType('mechListMIC', univ.Integer())
)

View File

@@ -137,12 +137,14 @@ class RDPClientController(pdu.layer.PDUClientListener):
def setSecurityLevel(self, level): def setSecurityLevel(self, level):
""" """
@summary: Request basic security @summary: Request basic security
@param level: {str} (ssl | rdp) @param level: {str} (ssl | rdp | nla)
""" """
if level == "rdp": if level == "rdp":
self._x224Layer._requestedProtocol = x224.Protocols.PROTOCOL_RDP self._x224Layer._requestedProtocol = x224.Protocols.PROTOCOL_RDP
elif level == "ssl": elif level == "ssl":
self._x224Layer._requestedProtocol = x224.Protocols.PROTOCOL_SSL self._x224Layer._requestedProtocol = x224.Protocols.PROTOCOL_SSL
elif level == "nla":
self._x224Layer._requestedProtocol = x224.Protocols.PROTOCOL_SSL | x224.Protocols.PROTOCOL_HYBRID
def addClientObserver(self, observer): def addClientObserver(self, observer):
""" """

View File

@@ -26,6 +26,8 @@ from rdpy.core.layer import RawLayer
from rdpy.core.type import UInt8, UInt16Be, sizeof from rdpy.core.type import UInt8, UInt16Be, sizeof
from rdpy.core.error import CallPureVirtualFuntion from rdpy.core.error import CallPureVirtualFuntion
from nla import cssp, ntlm
class Action(object): class Action(object):
""" """
@see: http://msdn.microsoft.com/en-us/library/cc240621.aspx @see: http://msdn.microsoft.com/en-us/library/cc240621.aspx
@@ -216,9 +218,10 @@ class TPKT(RawLayer, IFastPathSender):
""" """
self.transport.startTLS(sslContext) self.transport.startTLS(sslContext)
def startNLA(self, sslContext): def startNLA(self):
""" """
@summary: use to start NLA (NTLM over SSL) protocol @summary: use to start NLA (NTLM over SSL) protocol
@param sslContext: {ssl.ClientContextFactory | ssl.DefaultOpenSSLContextFactory} context use for NLA protocol must be called after startTLS function
""" """
self.transport.startTLS(sslContext) #send first NTLM packet
self.transport.write(cssp.createBERRequest( [ ntlm.NegotiateMessage() ] ))

View File

@@ -50,6 +50,7 @@ class NegociationType(object):
class Protocols(object): class Protocols(object):
""" """
@summary: Protocols available for x224 layer @summary: Protocols available for x224 layer
@see: https://msdn.microsoft.com/en-us/library/cc240500.aspx
""" """
PROTOCOL_RDP = 0x00000000 PROTOCOL_RDP = 0x00000000
PROTOCOL_SSL = 0x00000001 PROTOCOL_SSL = 0x00000001
@@ -132,7 +133,7 @@ class X224Layer(LayerAutomata, IStreamSender):
""" """
LayerAutomata.__init__(self, presentation) LayerAutomata.__init__(self, presentation)
#client requested selectedProtocol #client requested selectedProtocol
self._requestedProtocol = Protocols.PROTOCOL_SSL self._requestedProtocol = Protocols.PROTOCOL_SSL | Protocols.PROTOCOL_HYBRID
#server selected selectedProtocol #server selected selectedProtocol
self._selectedProtocol = Protocols.PROTOCOL_SSL self._selectedProtocol = Protocols.PROTOCOL_SSL
@@ -204,19 +205,22 @@ class Client(X224Layer):
self._selectedProtocol = Protocols.PROTOCOL_RDP self._selectedProtocol = Protocols.PROTOCOL_RDP
#NLA protocol doesn't support in actual version of RDPY #NLA protocol doesn't support in actual version of RDPY
if self._selectedProtocol in [ Protocols.PROTOCOL_HYBRID, Protocols.PROTOCOL_HYBRID_EX ]: if self._selectedProtocol in [ Protocols.PROTOCOL_HYBRID_EX ]:
raise InvalidExpectedDataException("RDPY doesn't support NLA security Layer") raise InvalidExpectedDataException("RDPY doesn't support PROTOCOL_HYBRID_EX security Layer")
if self._selectedProtocol == Protocols.PROTOCOL_SSL: if self._selectedProtocol in [ Protocols.PROTOCOL_SSL, Protocols.PROTOCOL_HYBRID ]:
log.debug("*" * 10 + " select SSL layer " + "*" * 10) log.debug("*" * 10 + " select SSL layer " + "*" * 10)
#_transport is TPKT and transport is TCP layer of twisted
self._transport.startTLS(ClientTLSContext()) self._transport.startTLS(ClientTLSContext())
#now i'm ready to receive data if self._selectedProtocol == Protocols.PROTOCOL_HYBRID:
self.setNextState(self.recvData) log.debug("*" * 10 + " select NLA layer " + "*" * 10)
self._transport.startNLA()
else:
#now i'm ready to receive data
self.setNextState(self.recvData)
#connection is done send to presentation #connection is done send to presentation
self._presentation.connect() self._presentation.connect()
class Server(X224Layer): class Server(X224Layer):
""" """