Esempio n. 1
0
  def dump( self, indent=0 ):
    # Produce a nicely formatted dump of the SMB2 header.
    #
    # Input:
    #   indent  - Number of spaces to indent the formatted output.
    #
    # Output: A string, presentng the formatted SMB2 header fields.
    #
    # Notes:  If the message is a request and the dialect is at least
    #         0x0300, the ChannelSequence (and a Reserved field) will
    #         replace the Status field (which would otherwise go unused
    #         in a request).  This is a protocol modification introduced
    #         with the 3.0 dialect.
    #
    ind = ' ' * indent
    cmdName  = self.commandName( self._command )
    cmdName  = "<unknown>" if( not cmdName ) else cmdName
    statName = NTStatus( self._status )
    statName = "\n" if( statName is None ) else " [%s]\n" % statName.name

    # Stuff...
    s  = ind + "ProtocolId...: %s\n" % hexstr( self._protocolId[:4] )
    s += ind + "StructureSize: 0x{0:04X} ({0:d})\n".format( self._headerSize )
    s += ind + "CreditCharge.: 0x{0:04X} ({0:d})\n".format( self._creditCharge )
    # Status/Reserved1
    if( self.flagReply or self._dialect < SMB2_DIALECT_300 ):
      s += ind + "Status.......: 0x{0:08X}".format( self._status ) + statName
    else:
      s += ind + "ChannelSeq...: 0x{0:04X} ({0:d})\n".format( self._channelSeq )
      s += ind + "Reserved1....: 0x{0:04X} ({0:d})\n".format( self._reserved1 )
    # More stuff...
    s += ind + "Command......: 0x{0:02X} ({0:d})".format( self._command ) \
             + " [{0:s}]\n".format( self.commandName( self._command ) )
    s += ind + "CreditReqResp: 0x{0:04X} ({0:d})\n".format( self.creditReqResp )
    s += ind + "Flags........: 0x{0:08X} ({0:d})\n".format( self._flags )
    # Flag subfields.
    s += ind + "  Response.....: %s\n" % self.flagReply
    s += ind + "  Async........: %s\n" % self.flagAsync
    s += ind + "  Related Op...: %s\n" % self.flagNext
    s += ind + "  Signed.......: %s\n" % self.flagSigned
    if( self._dialect >= SMB2_DIALECT_311 ):
      s += ind + "  Priority.....: {0:d}\n".format( self.flagPriority )
    s += ind + "  DFS Operation: %s\n" % self.flagDFS
    s += ind + "  SMB3.x Replay: %s\n" % self.flagReplay
    # Yet more stuff...
    s += ind + "NextCommand..: 0x{0:08X} ({0:d})\n".format( self._nextCommand )
    s += ind + "MessageId....: 0x{0:016X} ({0:d})\n".format( self._messageId )
    # AsyncId/Reserved2+TreeId
    if( self.flagAsync ):
      s += ind + "AsyncId......: 0x{0:016X} ({0:d})\n".format( self._asyncId )
    else:
      s += ind + "Reserved2....: 0x{0:08X} ({0:d})\n".format( self._reserved2 )
      s += ind + "TreeId.......: 0x{0:08X} ({0:d})\n".format( self._treeId )
    # SessionId and Signature
    s += ind + "SessionId....: 0x{0:016X} ({0:d})\n".format( self._sessionId )
    s += ind + "Signature....: ["
    tmp = (16 + indent)
    s += ('\n' + (' ' * tmp)).join( hexstrchop( self._signature, 32 ) ) + "]\n"
    return( s )
Esempio n. 2
0
def SessionRequest( CalledName, CallingName ):
  """Create an NBT Session Service Session Request message.

  Input:
    CalledName  - The name of the NBT service to which the message is
                  addressed.  There may be several named NBT services
                  listening on a given server.
    CallingName - The name of the NBT service or application that is
                  sending the session request.

  Errors: ValueError  - Thrown if either of the input paramaters does
                        not match the required format.  See the Notes.

  Output: A byte string.  The first four bytes are always
          [0x81, 0, 0, 0x44].  The remaining 68 bytes are the Called and
          Calling names provided.  The total length of the output will
          always be 72 bytes.

  Notes:  This function is mostly a set of sanity checks.

          The input parameters must each be L2-encoded NBT names *without
          NBT scope*.  This is an odditiy of the session service.  The NBT
          scope must not be used.  The resulting encoded name will always
          be 34 bytes in length.  The first byte will always be 0x20 and
          the last byte will always be 0x00.

  Doctest:
    >>> called = ' EHEPFCEHEPEOFKEPEMEBCACACACACACA\\0'
    >>> calling = ' EMEJENECFFFCEHEFFCFKCACACACACACA\\0'
    >>> req = SessionRequest( called, calling )
    >>> print "0x%02X" % ParseMsg( req )[0]
    0x81
    >>> called, calling = map( hexstr, ParseCNames( req[4:] ) )
    >>> print "Called.: [%s]\\nCalling: [%s]" % (called, calling)
    Called.: [ EHEPFCEHEPEOFKEPEMEBCACACACACACA\\x00]
    Calling: [ EMEJENECFFFCEHEFFCFKCACACACACACA\\x00]
  """
  # Check both names.
  if( not _L2Okay( CalledName ) ):
    raise ValueError( "Malformed Called Name: %s." % hexstr( CalledName ) )
  if( not _L2Okay( CallingName ) ):
    raise ValueError( "Malformed Calling Name: %s." % hexstr( CallingName ) )
  # Return the composed message.
  return( "\x81\0\0\x44" + CalledName + CallingName )
Esempio n. 3
0
def dump( msg=None, indent=0 ):
  """Parse and pretty print an NBT Session Service message.

  Input:  msg     - The (packed) NBT Session Service message.
          indent  - The number of spaces to indent the formatted output.

  Output: A string containing the formatted NBT message.  If the input
          is empty or None, the empty string is returned.

  Notes:  This function does its own parsing, and does not throw any
          exceptions if it finds a parsing error.  Instead, it just
          adds the error information to the output.

          If the message is a Session Message, this function does not
          dump the payload.  That should be handled by the higher
          level protocol stack.

  Doctest:
  >>> print dump( SessionMessage( 1234 ) + "Extra Junk" )
  Message Type: 0x00 [Session Message]
  Flags.......: 0x00
  Length......: 1234
  >>> called, calling = map( Name, ("CALLED", "CALLING") )
  >>> print dump( SessionRequest( called.L2name, calling.L2name ) )
  Message Type: 0x81 [Session Request]
  Flags.......: 0x00
  Length......: 68
  Called Name.: [ EDEBEMEMEFEECACACACACACACACACACA\\x00]
                CALLED<20>
  Calling Name: [ EDEBEMEMEJEOEHCACACACACACACACACA\\x00]
                CALLING<20>
  >>> print dump( PositiveResponse() )
  Message Type: 0x82 [Positive Session Response]
  Flags.......: 0x00
  Length......: 0
  """
  def _decodeL2( nom=None ):
    # Small sub-function to decode L2 NBT names.
    if( _L2Okay( nom ) ):
      n = Name()
      n.setL2name( nom )
      return( str( n ) )
    return( "<Cannot Decode>" )

  # Prepare your spells.
  ind   = ' ' * indent    # The correct number of spaces for indentation.
  inLen = len( msg )      # Length of the input, in bytes.

  # Check for secret doors and traps.
  if( not msg ):
    return( "" )
  if( inLen < 4 ):
    return( ind + "Short input: %s" % hexstr( msg ) )

  # Enter the dungeon.
  mType  = ord( msg[0] )
  mFlags = (ord( msg[1] ) >> 1)
  mLen   = _formatLong.unpack( msg[:4] )[0] & 0x0001FFFF

  # Loot the room.
  s = "{0:s}Message Type: 0x{1:02X} [{2:s}]\n" \
      "{0:s}Flags.......: 0x{3:02X}{4:s}\n"    \
      "{0:s}Length......: {5:d}{6:s}"

  # Go looking for trouble.
  fstr = "" if not mFlags else " <Invalid Flags>"
  validstr = ""
  if( (mType in _msgLenDict) and (mLen != _msgLenDict[mType]) ):
    validstr = " <Invalid Length>"
  s = s.format( ind, mType, MsgTypeStr( mType ), mFlags, fstr, mLen, validstr )

  # Deal with the monsters.
  if( (mType in _msgLenDict) and (inLen < (4 + _msgLenDict[mType])) ):
    s += "\n%sShort input.: %s" % (ind, hexstr( msg[4:] ))
  elif( mType == SS_SESSION_REQUEST ):
    called, calling = (msg[4:38], msg[38:72])
    s += "\n%sCalled Name.: [%s]" % (ind, hexstr( called ))
    s += "\n%s              %s" % (ind, _decodeL2( called ))
    s += "\n%sCalling Name: [%s]" % (ind, hexstr( calling ))
    s += "\n%s              %s" % (ind, _decodeL2( calling ))
  elif( mType == SS_NEGATIVE_RESPONSE ):
    eCode = ord(msg[4])
    s += "\n%sError Code..: 0x%02X (%s)" % (ind, eCode, ErrCodeStr( eCode ))
  elif( mType == SS_RETARGET_RESPONSE ):
    ip, port = _formatIPPort.unpack( msg[4:10] )
    s += "\n%sIPv4 Address: %d.%d.%d.%d" % (ind, ip[0], ip[1], ip[2], ip[3])
    s += "\n%sPort Number.: %d" % (ind, port)

  # Face the Gazebo Alone.
  return( s )