# coding: utf8
# This file is part of Scapy
# Scapy 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 2 of the License, or
# any later version.
#
# Scapy 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 Scapy. If not, see .
# Copyright (C)
# @Author: GuillaumeF
# @Email: guillaume4favre@gmail.com
# @Date: 2016-10-18
# @Last modified by: GuillaumeF
# @Last modified by: Sebastien Mainand
# @Last modified time: 2016-12-08 11:16:27
# @Last modified time: 2017-07-05
# scapy.contrib.description = OPC Data Access
# scapy.contrib.status = loads
"""
Opc Data Access.
References: Data Access Custom Interface StanDard
Using the website: http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
DCOM Remote Protocol.
References: Specifies Distributed Component Object Model (DCOM) Remote Protocol
Using the website: https://msdn.microsoft.com/en-us/library/cc226801.aspx
"""
from scapy.config import conf
from scapy.fields import Field, ByteField, ShortField, LEShortField, \
IntField, LEIntField, LongField, LELongField, StrField, StrLenField, \
StrFixedLenField, BitEnumField, ByteEnumField, ShortEnumField, \
LEShortEnumField, IntEnumField, LEIntEnumField, FieldLenField, \
LEFieldLenField, PacketField, PacketListField, PacketLenField, \
ConditionalField, FlagsField, UUIDField
from scapy.packet import Packet
# Defined values
_tagOPCDataSource = {
1: "OPC_DS_CACHE",
2: "OPC_DS_DEVICE"
}
_tagOPCBrowseType = {
1: "OPC_BRANCH",
2: "OPC_LEAF",
3: "OPC_FLAT"
}
_tagOPCNameSpaceType = {
1: "OPC_NS_HIERARCHIAL",
2: "OPC_NS_FLAT"
}
_tagOPCBrowseDirection = {
1: "OPC_BROWSE_UP",
2: "OPC_BROWSE_DOWN",
3: "OPC_BROWSE_TO"
}
_tagOPCEuType = {
0: "OPC_NOENUM",
1: "OPC_ANALOG",
2: "OPC_ENUMERATED"
}
_tagOPCServerState = {
1: "OPC_STATUS_RUNNING",
2: "OPC_STATUS_FAILED",
3: "OPC_STATUS_NOCONFIG",
4: "OPC_STATUS_SUSPENDED",
5: "OPC_STATUS_TEST",
6: "OPC_STATUS_COMM_FAULT"
}
_tagOPCEnumScope = {
1: "OPC_ENUM_PRIVATE_CONNECTIONS",
2: "OPC_ENUM_PUBLIC_CONNECTIONS",
3: "OPC_ENUM_ALL_CONNECTIONS",
4: "OPC_ENUM_PRIVATE",
5: "OPC_ENUM_PUBLIC",
6: "OPC_ENUM_ALL"
}
_pfc_flags = [
"firstFragment", # First fragment
"lastFragment", # Last fragment
"pendingCancel", # Cancel was pending at sender
"reserved", #
"concurrentMultiplexing", # supports concurrent multiplexing
# of a single connection
"didNotExecute", # only meaningful on `fault' packet if true,
# guaranteed call did not execute
"maybe", # `maybe' call semantics requested
"objectUuid" # if true, a non-nil object UUID was specified
# in the handle, and is present in the optional
# object field. If false, the object field
# is omitted
]
_faultStatus = {
382312475: 'rpc_s_fault_object_not_found',
382312497: 'rpc_s_call_cancelled',
382312564: 'rpc_s_fault_addr_error',
382312565: 'rpc_s_fault_context_mismatch',
382312566: 'rpc_s_fault_fp_div_by_zero',
382312567: 'rpc_s_fault_fp_error',
382312568: 'rpc_s_fault_fp_overflow',
382312569: 'rpc_s_fault_fp_underflow',
382312570: 'rpc_s_fault_ill_inst',
382312571: 'rpc_s_fault_int_div_by_zero',
382312572: 'rpc_s_fault_int_overflow',
382312573: 'rpc_s_fault_invalid_bound',
382312574: 'rpc_s_fault_invalid_tag',
382312575: 'rpc_s_fault_pipe_closed',
382312576: 'rpc_s_fault_pipe_comm_error',
382312577: 'rpc_s_fault_pipe_discipline',
382312578: 'rpc_s_fault_pipe_empty',
382312579: 'rpc_s_fault_pipe_memory',
382312580: 'rpc_s_fault_pipe_order',
382312582: 'rpc_s_fault_remote_no_memory',
382312583: 'rpc_s_fault_unspec',
382312723: 'rpc_s_fault_user_defined',
382312726: 'rpc_s_fault_tx_open_failed',
382312814: 'rpc_s_fault_codeset_conv_error',
382312816: 'rpc_s_fault_no_client_stub',
469762049: 'nca_s_fault_int_div_by_zero',
469762050: 'nca_s_fault_addr_error',
469762051: 'nca_s_fault_fp_div_zero',
469762052: 'nca_s_fault_fp_underflow',
469762053: 'nca_s_fault_fp_overflow',
469762054: 'nca_s_fault_invalid_tag',
469762055: 'nca_s_fault_invalid_bound',
469762061: 'nca_s_fault_cancel',
469762062: 'nca_s_fault_ill_inst',
469762063: 'nca_s_fault_fp_error',
469762064: 'nca_s_fault_int_overflow',
469762068: 'nca_s_fault_pipe_empty',
469762069: 'nca_s_fault_pipe_closed',
469762070: 'nca_s_fault_pipe_order',
469762071: 'nca_s_fault_pipe_discipline',
469762072: 'nca_s_fault_pipe_comm_error',
469762073: 'nca_s_fault_pipe_memory',
469762074: 'nca_s_fault_context_mismatch',
469762075: 'nca_s_fault_remote_no_memory',
469762081: 'ncs_s_fault_user_defined',
469762082: 'nca_s_fault_tx_open_failed',
469762083: 'nca_s_fault_codeset_conv_error',
469762084: 'nca_s_fault_object_not_found',
469762085: 'nca_s_fault_no_client_stub',
}
_defResult = {
0: 'ACCEPTANCE',
1: 'USER_REJECTION',
2: 'PROVIDER_REJECTION',
}
_defReason = {
0: 'REASON_NOT_SPECIFIED',
1: 'ABSTRACT_SYNTAX_NOT_SUPPORTED',
2: 'PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED',
3: 'LOCAL_LIMIT_EXCEEDED',
}
_rejectBindNack = {
0: 'REASON_NOT_SPECIFIED',
1: 'TEMPORARY_CONGESTION',
2: 'LOCAL_LIMIT_EXCEEDED',
3: 'CALLED_PADDR_UNKNOWN',
4: 'PROTOCOL_VERSION_NOT_SUPPORTED',
5: 'DEFAULT_CONTEXT_NOT_SUPPORTED',
6: 'USER_DATA_NOT_READABLE',
7: 'NO_PSAP_AVAILABLE'
}
_rejectStatus = {
469762056: 'nca_rpc_version_mismatch',
469762057: 'nca_unspec_reject',
469762058: 'nca_s_bad_actid',
469762059: 'nca_who_are_you_failed',
469762060: 'nca_manager_not_entered',
469827586: 'nca_op_rng_error',
469827587: 'nca_unk_if',
469827590: 'nca_wrong_boot_time',
469827593: 'nca_s_you_crashed',
469827595: 'nca_proto_error',
469827603: 'nca_out_args_too_big',
469827604: 'nca_server_too_busy',
469827607: 'nca_unsupported_type',
469762076: 'nca_invalid_pres_context_id',
469762077: 'nca_unsupported_authn_level',
469762079: 'nca_invalid_checksum',
469762080: 'nca_invalid_crc'
}
_pduType = {
0: "REQUEST",
1: "PING",
2: "RESPONSE",
3: "FAULT",
4: "WORKING",
5: "NOCALL",
6: "REJECT",
7: "ACK",
8: "CI_CANCEL",
9: "FACK",
10: "CANCEL_ACK",
11: "BIND",
12: "BIND_ACK",
13: "BIND_NACK",
14: "ALTER_CONTEXT",
15: "ALTER_CONTEXT_RESP",
17: "SHUTDOWN",
18: "CO_CANCEL",
19: "ORPHANED",
# Not documented
16: "Auth3",
}
_authentification_protocol = {
0: 'None',
1: 'OsfDcePrivateKeyAuthentication',
}
# Sub class for dissection
class AuthentificationProtocol(Packet):
name = 'authentificationProtocol'
def extract_padding(self, p):
return b"", p
def guess_payload_class(self, payload):
if self.underlayer and hasattr(self.underlayer, "auth_length"):
auth_length = self.underlayer.auth_length
if auth_length != 0:
try:
return _authentification_protocol[auth_length]
except Exception:
pass
return conf.raw_layer
class OsfDcePrivateKeyAuthentification(Packet):
name = "OsfDcePrivateKeyAuthentication"
# TODO
def extract_padding(self, p):
return b"", p
class OPCHandle(Packet):
def __init__(self, name, default):
Field.__init__(self, name, default, "16s")
def extract_padding(self, p):
return b"", p
class LenStringPacket(Packet):
name = "len string packet"
fields_desc = [
FieldLenField('length', 0, length_of='data', fmt="H"),
ConditionalField(StrLenField('data', None,
length_from=lambda pkt:pkt.length + 2),
lambda pkt:pkt.length == 0),
ConditionalField(StrLenField('data', '',
length_from=lambda pkt:pkt.length),
lambda pkt:pkt.length != 0),
]
def extract_padding(self, p):
return b"", p
class LenStringPacketLE(Packet):
name = "len string packet"
fields_desc = [
LEFieldLenField('length', 0, length_of='data', fmt="