mirror of
https://github.com/zeek/zeek.git
synced 2025-10-01 22:28:20 +00:00
analyzer/protocol: Reformat with spicy-format
This commit is contained in:
parent
aa2afa3e9b
commit
d70bcd07b9
6 changed files with 1433 additions and 1519 deletions
|
@ -55,5 +55,4 @@ repos:
|
|||
rev: v0.26.0
|
||||
hooks:
|
||||
- id: spicy-format
|
||||
# TODO: Reformat existing large analyzers just before 8.0.
|
||||
exclude: '(^testing/.*)|(protocol/ldap/.*)|(protocol/quic/.*)|(protocol/websocket/.*)'
|
||||
exclude: '^testing/.*'
|
||||
|
|
|
@ -50,7 +50,7 @@ public type ASN1Type = enum {
|
|||
GeneralString = 27,
|
||||
UniversalString = 28,
|
||||
CharacterString = 29,
|
||||
BMPString = 30
|
||||
BMPString = 30,
|
||||
};
|
||||
|
||||
#- ASN.1 data classes --------------------------------------------------------
|
||||
|
@ -59,7 +59,7 @@ public type ASN1Class = enum {
|
|||
Universal = 0,
|
||||
Application = 1,
|
||||
ContextSpecific = 2,
|
||||
Private = 3
|
||||
Private = 3,
|
||||
};
|
||||
|
||||
#- ASN.1 tag definition (including length) ------------------------------------
|
||||
|
@ -73,14 +73,12 @@ type LengthType = unit {
|
|||
islong: 7;
|
||||
};
|
||||
|
||||
|
||||
switch (self.data.islong) {
|
||||
0 -> : void {
|
||||
self.len = self.data.num;
|
||||
self.tag_len = 1;
|
||||
}
|
||||
1 -> : bytes &size=self.data.num
|
||||
&convert=$$.to_uint(spicy::ByteOrder::Network) {
|
||||
1 -> : bytes &size=self.data.num &convert=$$.to_uint(spicy::ByteOrder::Network) {
|
||||
self.len = $$;
|
||||
self.tag_len = self.data.num + 1;
|
||||
}
|
||||
|
@ -128,13 +126,11 @@ type ASN1String = unit(tag: ASN1Tag, len: uint64) {
|
|||
# see "Restricted Character String Types" in
|
||||
# "Generic String Encoding Rules (GSER) for ASN.1 Types"
|
||||
# (https://datatracker.ietf.org/doc/html/rfc3641#section-3.2)
|
||||
|
||||
case ASN1Type::PrintableString,
|
||||
ASN1Type::GeneralizedTime,
|
||||
ASN1Type::UTCTime: {
|
||||
self.encoding = spicy::Charset::ASCII;
|
||||
}
|
||||
|
||||
case ASN1Type::UTF8String,
|
||||
ASN1Type::GeneralString,
|
||||
ASN1Type::CharacterString,
|
||||
|
@ -192,7 +188,6 @@ type ASN1ObjectIdentifier = unit(len: uint64) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
#- ASN.1 message header (tag + length information) ----------------------------
|
||||
|
||||
public type ASN1Header = unit {
|
||||
|
@ -204,23 +199,13 @@ public type ASN1Header = unit {
|
|||
|
||||
public type ASN1Body = unit(head: ASN1Header, recursive: bool) {
|
||||
switch (head.tag.type_) {
|
||||
|
||||
ASN1Type::Boolean -> bool_value: uint8 &convert=cast<bool>($$) &requires=head.len.len == 1;
|
||||
|
||||
ASN1Type::Integer,
|
||||
ASN1Type::Enumerated -> num_value: bytes &size=head.len.len
|
||||
&convert=$$.to_int(spicy::ByteOrder::Big);
|
||||
|
||||
ASN1Type::Enumerated -> num_value: bytes &size=head.len.len &convert=$$.to_int(spicy::ByteOrder::Big);
|
||||
ASN1Type::NullVal -> null_value: bytes &size=0 &requires=head.len.len == 0;
|
||||
|
||||
ASN1Type::BitString -> bitstr_value: ASN1BitString(head.len.len, head.tag.constructed);
|
||||
|
||||
ASN1Type::OctetString -> str_value: ASN1OctetString(head.len.len, head.tag.constructed)
|
||||
&convert=$$.value.decode(spicy::Charset::ASCII);
|
||||
|
||||
ASN1Type::ObjectIdentifier -> str_value: ASN1ObjectIdentifier(head.len.len)
|
||||
&convert=$$.oidstring;
|
||||
|
||||
ASN1Type::OctetString -> str_value: ASN1OctetString(head.len.len, head.tag.constructed) &convert=$$.value.decode(spicy::Charset::ASCII);
|
||||
ASN1Type::ObjectIdentifier -> str_value: ASN1ObjectIdentifier(head.len.len) &convert=$$.oidstring;
|
||||
ASN1Type::BMPString,
|
||||
ASN1Type::CharacterString,
|
||||
ASN1Type::GeneralizedTime,
|
||||
|
@ -235,8 +220,8 @@ public type ASN1Body = unit(head: ASN1Header, recursive: bool) {
|
|||
ASN1Type::VideotextString,
|
||||
ASN1Type::VisibleString,
|
||||
ASN1Type::UniversalString -> str_value: ASN1String(head.tag, head.len.len);
|
||||
|
||||
ASN1Type::Sequence, ASN1Type::Set -> seq: ASN1SubMessages(head.len.len) if (recursive);
|
||||
ASN1Type::Sequence,
|
||||
ASN1Type::Set -> seq: ASN1SubMessages(head.len.len) if(recursive);
|
||||
|
||||
# TODO: ASN1Type values not handled yet
|
||||
ASN1Type::ObjectDescriptor,
|
||||
|
@ -266,14 +251,11 @@ public type ASN1Message = unit(recursive: bool) {
|
|||
|
||||
head: ASN1Header;
|
||||
switch (self.head.tag.class) {
|
||||
|
||||
ASN1Class::Universal -> body: ASN1Body(self.head, recursive);
|
||||
|
||||
ASN1Class::Application,
|
||||
ASN1Class::ContextSpecific,
|
||||
ASN1Class::Private -> application_data: bytes &size=self.head.len.len {
|
||||
self.application_id = cast<int32>(self.head.tag.type_);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -115,12 +115,9 @@ public type ResultCode = enum {
|
|||
|
||||
#-----------------------------------------------------------------------------
|
||||
public type Result = unit {
|
||||
code: ASN1::ASN1Message(True) &convert=cast<ResultCode>(cast<uint8>($$.body.num_value))
|
||||
&default=ResultCode::Undef;
|
||||
matchedDN: ASN1::ASN1Message(True) &convert=$$.body.str_value
|
||||
&default="";
|
||||
diagnosticMessage: ASN1::ASN1Message(True) &convert=$$.body.str_value
|
||||
&default="";
|
||||
code: ASN1::ASN1Message(True) &convert=cast<ResultCode>(cast<uint8>($$.body.num_value)) &default=ResultCode::Undef;
|
||||
matchedDN: ASN1::ASN1Message(True) &convert=$$.body.str_value &default="";
|
||||
diagnosticMessage: ASN1::ASN1Message(True) &convert=$$.body.str_value &default="";
|
||||
|
||||
# TODO: if we want to parse referral URIs in result
|
||||
# https://tools.ietf.org/html/rfc4511#section-4.1.10
|
||||
|
@ -162,7 +159,6 @@ public type MessageDispatch = unit(ctx: Ctx&) {
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
type MaybeEncrypted = unit(ctx: Ctx&) {
|
||||
# A plaintext LDAP message always starts with at least 3 bytes and the first
|
||||
|
@ -242,7 +238,8 @@ type KrbWrapToken = unit {
|
|||
};
|
||||
filler: skip b"\xff";
|
||||
ec: uint16; # extra count
|
||||
rrc: uint16 { # right rotation count
|
||||
rrc: uint16 {
|
||||
# right rotation count
|
||||
# Handle rrc == ec or rrc == 0.
|
||||
if (self.rrc == self.ec) {
|
||||
self.header_ec = self.ec;
|
||||
|
@ -406,7 +403,7 @@ type GSS_SPNEGO_Init = unit {
|
|||
spnegoInitial: skip GSS_SPNEGO_negTokenInit if(self?.spnegoInitByte);
|
||||
};
|
||||
|
||||
type SaslCredentials = unit() {
|
||||
type SaslCredentials = unit {
|
||||
mechanism: ASN1::ASN1Message(False) &convert=$$.body.str_value;
|
||||
|
||||
# Peak into GSS-SPNEGO payload if we have any.
|
||||
|
@ -416,7 +413,7 @@ type SaslCredentials = unit() {
|
|||
};
|
||||
};
|
||||
|
||||
type SicilyMessage = unit() {
|
||||
type SicilyMessage = unit {
|
||||
# Just ensure the signature matches. We could do more,
|
||||
# but it'd be better to forward to an NTLM analyzer.
|
||||
signature: skip b"NTLMSSP";
|
||||
|
@ -486,23 +483,18 @@ type BindRequest = unit(inout message: Message, ctx: Ctx&) {
|
|||
|
||||
if (|self.authData| > 0) {
|
||||
switch (self.authType) {
|
||||
BindAuthType::BIND_AUTH_SIMPLE ->
|
||||
: void {
|
||||
BindAuthType::BIND_AUTH_SIMPLE -> : void {
|
||||
self.simpleCreds = self.authData.decode();
|
||||
message.arg = self.simpleCreds;
|
||||
}
|
||||
|
||||
BindAuthType::BIND_AUTH_SASL ->
|
||||
saslCreds: SaslCredentials {
|
||||
BindAuthType::BIND_AUTH_SASL -> saslCreds: SaslCredentials {
|
||||
message.arg = self.saslCreds.mechanism;
|
||||
ctx.saslMechanism = self.saslCreds.mechanism;
|
||||
}
|
||||
|
||||
BindAuthType::SICILY_NEGOTIATE, BindAuthType::SICILY_RESPONSE ->
|
||||
sicilyMessage: SicilyMessage {
|
||||
BindAuthType::SICILY_NEGOTIATE,
|
||||
BindAuthType::SICILY_RESPONSE -> sicilyMessage: SicilyMessage {
|
||||
message.arg = self.sicilyMessage.signature_decoded;
|
||||
}
|
||||
|
||||
* -> : void;
|
||||
} &parse-from=self.authData;
|
||||
};
|
||||
|
@ -543,8 +535,7 @@ type BindResponse = unit(inout message: Message, ctx: Ctx&) {
|
|||
|
||||
# If the client requested GSS-SPNEGO, try to parse the server's response
|
||||
# to switch message mode.
|
||||
gss_spnego: GSS_SPNEGO_Subsequent &parse-from=self.serverSaslCreds[0].payload
|
||||
if (ctx.saslMechanism == "GSS-SPNEGO" && |self.serverSaslCreds| > 0) {
|
||||
gss_spnego: GSS_SPNEGO_Subsequent &parse-from=self.serverSaslCreds[0].payload if(ctx.saslMechanism == "GSS-SPNEGO" && |self.serverSaslCreds| > 0) {
|
||||
|
||||
if ($$?.negTokenResp) {
|
||||
local token = $$.negTokenResp;
|
||||
|
@ -603,8 +594,7 @@ public type AttributeSelection = unit {
|
|||
# https://tools.ietf.org/html/rfc4511#section-4.5.1
|
||||
# and decide how deep that should be fleshed out.
|
||||
: ASN1::ASN1Message(True) {
|
||||
if (($$.head.tag.type_ == ASN1::ASN1Type::Sequence) &&
|
||||
($$.body?.seq)) {
|
||||
if (($$.head.tag.type_ == ASN1::ASN1Type::Sequence) && ($$.body?.seq)) {
|
||||
for (i in $$.body.seq.submessages) {
|
||||
if (i.body?.str_value) {
|
||||
self.attributes.push_back(i.body.str_value);
|
||||
|
@ -619,9 +609,7 @@ type AttributeValueAssertion = unit {
|
|||
var val: string = "";
|
||||
|
||||
: ASN1::ASN1Message(True) {
|
||||
if (($$.head.tag.type_ == ASN1::ASN1Type::Sequence) &&
|
||||
($$.body?.seq) &&
|
||||
(|$$.body.seq.submessages| >= 2)) {
|
||||
if (($$.head.tag.type_ == ASN1::ASN1Type::Sequence) && ($$.body?.seq) && (|$$.body.seq.submessages| >= 2)) {
|
||||
if ($$.body.seq.submessages[0].body?.str_value) {
|
||||
self.desc = $$.body.seq.submessages[0].body.str_value;
|
||||
}
|
||||
|
@ -715,7 +703,6 @@ public function bytes_sid_to_SID_repr(bts: bytes) : string {
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
public function uint32_to_hex_repr(bts: bytes): string {
|
||||
# Needs to be exactly 4 bytes
|
||||
if (|bts| != 4) {
|
||||
|
@ -739,12 +726,11 @@ public function string_representation(search_filter: SearchFilter): string {
|
|||
switch (local fType = search_filter.filterType) {
|
||||
# The NOT, AND and OR filter types are trees and may hold many leaf nodes. So recursively get
|
||||
# the stringPresentations for the leaf nodes and add them all in one final statement.
|
||||
|
||||
case FilterType::FILTER_NOT: {
|
||||
repr = "(!%s)" % search_filter.FILTER_NOT.searchfilter.stringRepresentation;
|
||||
}
|
||||
|
||||
case FilterType::FILTER_AND, FilterType::FILTER_OR: {
|
||||
case FilterType::FILTER_AND,
|
||||
FilterType::FILTER_OR: {
|
||||
local nestedObj: ParseNestedAndOr;
|
||||
local printChar = "";
|
||||
|
||||
|
@ -780,12 +766,9 @@ public function string_representation(search_filter: SearchFilter): string {
|
|||
for (searchFilter in nestedObj.searchfilters) {
|
||||
switch (i) {
|
||||
case 0: {
|
||||
repr = "(%s%s%s" % (
|
||||
printChar,
|
||||
searchFilter.stringRepresentation,
|
||||
repr = "(%s%s%s" % (printChar, searchFilter.stringRepresentation,
|
||||
# If we have exactly one element immediately close the statement since we are done.
|
||||
|nestedObj.searchfilters| == 1 ? ")" : ""
|
||||
);
|
||||
|nestedObj.searchfilters| == 1 ? ")" : "");
|
||||
}
|
||||
case 1: {
|
||||
repr = repr + searchFilter.stringRepresentation + ")";
|
||||
|
@ -799,39 +782,29 @@ public function string_representation(search_filter: SearchFilter): string {
|
|||
}
|
||||
|
||||
# The following FilterTypes are leaf nodes and can thus be represented in a statement
|
||||
|
||||
case FilterType::FILTER_EXT: {
|
||||
# For extended search filters the meaning of the individual fields in
|
||||
# `DecodedAttributeValue` is slightly different.
|
||||
repr = "(%s:%s:=%s)" % (search_filter.FILTER_EXT.assertionValueDecoded,
|
||||
search_filter.FILTER_EXT.attributeDesc.decode(),
|
||||
search_filter.FILTER_EXT.matchValue);
|
||||
repr = "(%s:%s:=%s)" % (search_filter.FILTER_EXT.assertionValueDecoded, search_filter.FILTER_EXT.attributeDesc.decode(), search_filter.FILTER_EXT.matchValue);
|
||||
}
|
||||
case FilterType::FILTER_APPROX: {
|
||||
repr = "(%s~=%s)" % (search_filter.FILTER_APPROX.attributeDesc.decode(),
|
||||
search_filter.FILTER_APPROX.assertionValueDecoded);
|
||||
repr = "(%s~=%s)" % (search_filter.FILTER_APPROX.attributeDesc.decode(), search_filter.FILTER_APPROX.assertionValueDecoded);
|
||||
}
|
||||
case FilterType::FILTER_EQ: {
|
||||
repr = "(%s=%s)" % (search_filter.FILTER_EQ.attributeDesc.decode(),
|
||||
search_filter.FILTER_EQ.assertionValueDecoded);
|
||||
repr = "(%s=%s)" % (search_filter.FILTER_EQ.attributeDesc.decode(), search_filter.FILTER_EQ.assertionValueDecoded);
|
||||
}
|
||||
case FilterType::FILTER_GE: {
|
||||
repr = "(%s>=%s)" % (search_filter.FILTER_GE.attributeDesc.decode(),
|
||||
search_filter.FILTER_GE.assertionValueDecoded);
|
||||
repr = "(%s>=%s)" % (search_filter.FILTER_GE.attributeDesc.decode(), search_filter.FILTER_GE.assertionValueDecoded);
|
||||
}
|
||||
case FilterType::FILTER_LE: {
|
||||
repr = "(%s<=%s)" % (search_filter.FILTER_LE.attributeDesc.decode(),
|
||||
search_filter.FILTER_LE.assertionValueDecoded);
|
||||
repr = "(%s<=%s)" % (search_filter.FILTER_LE.attributeDesc.decode(), search_filter.FILTER_LE.assertionValueDecoded);
|
||||
}
|
||||
case FilterType::FILTER_SUBSTR: {
|
||||
local anys: string = "";
|
||||
if (|search_filter.FILTER_SUBSTR.anys| > 0)
|
||||
anys = b"*".join(search_filter.FILTER_SUBSTR.anys).decode() + "*";
|
||||
|
||||
repr = "(%s=%s*%s%s)" % (search_filter.FILTER_SUBSTR.attributeDesc.decode(),
|
||||
search_filter.FILTER_SUBSTR.initial,
|
||||
anys,
|
||||
search_filter.FILTER_SUBSTR.final);
|
||||
repr = "(%s=%s*%s%s)" % (search_filter.FILTER_SUBSTR.attributeDesc.decode(), search_filter.FILTER_SUBSTR.initial, anys, search_filter.FILTER_SUBSTR.final);
|
||||
}
|
||||
case FilterType::FILTER_PRESENT: {
|
||||
repr = "(%s=*)" % search_filter.FILTER_PRESENT;
|
||||
|
@ -862,19 +835,16 @@ type DecodedAttributeValue = unit(fType: FilterType) {
|
|||
switch (self.attributeDesc) {
|
||||
# Special parsing required for some CLDAP attributes,
|
||||
# see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/895a7744-aff3-4f64-bcfa-f8c05915d2e9
|
||||
|
||||
case b"DomainGuid": {
|
||||
self.assertionValueDecoded = utf16_guid_to_hex_repr(self.assertionValue);
|
||||
}
|
||||
|
||||
case b"objectSid", b"AAC": {
|
||||
case b"objectSid",
|
||||
b"AAC": {
|
||||
self.assertionValueDecoded = bytes_sid_to_hex_repr(self.assertionValue);
|
||||
}
|
||||
|
||||
case b"DomainSid": {
|
||||
self.assertionValueDecoded = bytes_sid_to_SID_repr(self.assertionValue);
|
||||
}
|
||||
|
||||
case b"NtVer": {
|
||||
self.assertionValueDecoded = uint32_to_hex_repr(self.assertionValue);
|
||||
}
|
||||
|
@ -933,31 +903,18 @@ type SearchFilter = unit {
|
|||
switch (self.filterType) {
|
||||
|
||||
# FilterTypes that hold one or more SearchFilters inside them
|
||||
|
||||
FilterType::FILTER_AND -> FILTER_AND: ParseNestedAndOr()
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_OR -> FILTER_OR: ParseNestedAndOr()
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_NOT -> FILTER_NOT: ParseNestedNot()
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_AND -> FILTER_AND: ParseNestedAndOr() &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_OR -> FILTER_OR: ParseNestedAndOr() &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_NOT -> FILTER_NOT: ParseNestedNot() &parse-from=self.filterBytes;
|
||||
|
||||
# FilterTypes that we can actually convert to a string
|
||||
|
||||
FilterType::FILTER_EQ -> FILTER_EQ: DecodedAttributeValue(FilterType::FILTER_EQ)
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_SUBSTR -> FILTER_SUBSTR: SubstringFilter
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_GE -> FILTER_GE: DecodedAttributeValue(FilterType::FILTER_GE)
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_LE -> FILTER_LE: DecodedAttributeValue(FilterType::FILTER_LE)
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_APPROX -> FILTER_APPROX: DecodedAttributeValue(FilterType::FILTER_APPROX)
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_EXT -> FILTER_EXT: DecodedAttributeValue(FilterType::FILTER_EXT)
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_PRESENT -> FILTER_PRESENT: ASN1::ASN1OctetString(self.filterLen, False)
|
||||
&convert=$$.value.decode(spicy::Charset::ASCII)
|
||||
&parse-from=self.filterBytes;
|
||||
FilterType::FILTER_EQ -> FILTER_EQ: DecodedAttributeValue(FilterType::FILTER_EQ) &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_SUBSTR -> FILTER_SUBSTR: SubstringFilter &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_GE -> FILTER_GE: DecodedAttributeValue(FilterType::FILTER_GE) &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_LE -> FILTER_LE: DecodedAttributeValue(FilterType::FILTER_LE) &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_APPROX -> FILTER_APPROX: DecodedAttributeValue(FilterType::FILTER_APPROX) &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_EXT -> FILTER_EXT: DecodedAttributeValue(FilterType::FILTER_EXT) &parse-from=self.filterBytes;
|
||||
FilterType::FILTER_PRESENT -> FILTER_PRESENT: ASN1::ASN1OctetString(self.filterLen, False) &convert=$$.value.decode(spicy::Charset::ASCII) &parse-from=self.filterBytes;
|
||||
};
|
||||
|
||||
# So when you're done with recursively parsing the filters, we can now leverage the tree structure to
|
||||
|
@ -970,19 +927,16 @@ type SearchFilter = unit {
|
|||
on %error {
|
||||
self.stringRepresentation = "FILTER_PARSING_ERROR";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public type SearchRequest = unit(inout message: Message) {
|
||||
baseObject: ASN1::ASN1Message(True) &convert=$$.body.str_value {
|
||||
message.obj = self.baseObject;
|
||||
}
|
||||
scope: ASN1::ASN1Message(True) &convert=cast<SearchScope>(cast<uint8>($$.body.num_value))
|
||||
&default=SearchScope::Undef {
|
||||
scope: ASN1::ASN1Message(True) &convert=cast<SearchScope>(cast<uint8>($$.body.num_value)) &default=SearchScope::Undef {
|
||||
message.arg = "%s" % self.scope;
|
||||
}
|
||||
deref: ASN1::ASN1Message(True) &convert=cast<SearchDerefAlias>(cast<uint8>($$.body.num_value))
|
||||
&default=SearchDerefAlias::Undef;
|
||||
deref: ASN1::ASN1Message(True) &convert=cast<SearchDerefAlias>(cast<uint8>($$.body.num_value)) &default=SearchDerefAlias::Undef;
|
||||
sizeLimit: ASN1::ASN1Message(True) &convert=$$.body.num_value &default=0;
|
||||
timeLimit: ASN1::ASN1Message(True) &convert=$$.body.num_value &default=0;
|
||||
typesOnly: ASN1::ASN1Message(True) &convert=$$.body.bool_value &default=False;
|
||||
|
@ -1110,9 +1064,7 @@ type ExtendedRequest = unit(inout message: Message, ctx: Ctx&) {
|
|||
}
|
||||
|
||||
# If there's more byte to parse, it's the requestValue.
|
||||
: ASN1::ASN1Message(False)
|
||||
&requires=($$.head.tag.class == ASN1::ASN1Class::ContextSpecific)
|
||||
if ( message.opLen > self.offset() ) {
|
||||
: ASN1::ASN1Message(False) &requires=($$.head.tag.class == ASN1::ASN1Class::ContextSpecific) if(message.opLen > self.offset()) {
|
||||
|
||||
self.requestValue = $$.application_data;
|
||||
}
|
||||
|
|
|
@ -7,15 +7,7 @@ import spicy;
|
|||
import zeek;
|
||||
|
||||
# The interface to the C++ code that handles the decryption of the INITIAL packet payload using well-known keys
|
||||
public function decrypt_crypto_payload(
|
||||
version: uint32,
|
||||
data: bytes,
|
||||
connection_id: bytes,
|
||||
encrypted_offset: uint64,
|
||||
payload_offset: uint64,
|
||||
from_client: bool
|
||||
): bytes &cxxname="QUIC_decrypt_crypto_payload";
|
||||
|
||||
public function decrypt_crypto_payload(version: uint32, data: bytes, connection_id: bytes, encrypted_offset: uint64, payload_offset: uint64, from_client: bool): bytes &cxxname="QUIC_decrypt_crypto_payload";
|
||||
|
||||
# Can we decrypt?
|
||||
function can_decrypt(long_header: LongHeaderPacket, context: Context, crypto: CryptoSinkUnit&): bool {
|
||||
|
@ -76,7 +68,8 @@ type CryptoSinkUnit = unit(is_orig: bool, context: Context&) {
|
|||
self.buffered += $$[2];
|
||||
}
|
||||
|
||||
: void &requires=(self.length <= 2**14 + 256) { # The length MUST NOT exceed 2^14 + 256 bytes (RFC 8446)
|
||||
: void &requires=(self.length <= 2**14 + 256) {
|
||||
# The length MUST NOT exceed 2^14 + 256 bytes (RFC 8446)
|
||||
|
||||
# The client or server hello data is forwarded to the SSL analyzer as a
|
||||
# TLSPlaintext record with legacy_record_version set to \x03\x03 (1.3).
|
||||
|
@ -246,13 +239,9 @@ public type LongHeaderPacketV1 = unit(inout outer: LongHeaderPacket) {
|
|||
switch (LongPacketTypeV1(outer.first_byte.packet_type)) {
|
||||
LongPacketTypeV1::INITIAL -> initial_hdr: InitialPacket(outer) {
|
||||
outer.is_initial = True;
|
||||
outer.encrypted_offset = outer.offset() +
|
||||
self.initial_hdr.length.bytes_to_parse +
|
||||
self.initial_hdr.token_length.bytes_to_parse +
|
||||
self.initial_hdr.token_length.result_;
|
||||
outer.encrypted_offset = outer.offset() + self.initial_hdr.length.bytes_to_parse + self.initial_hdr.token_length.bytes_to_parse + self.initial_hdr.token_length.result_;
|
||||
outer.payload_length = self.initial_hdr.length.result_;
|
||||
}
|
||||
|
||||
LongPacketTypeV1::ZERO_RTT -> zerortt_hdr: ZeroRTTPacket(outer);
|
||||
LongPacketTypeV1::HANDSHAKE -> handshake_hdr: HandshakePacket(outer);
|
||||
LongPacketTypeV1::RETRY -> retry_hdr: RetryPacket(outer) {
|
||||
|
@ -265,13 +254,9 @@ public type LongHeaderPacketV2 = unit(inout outer: LongHeaderPacket) {
|
|||
switch (LongPacketTypeV2(outer.first_byte.packet_type)) {
|
||||
LongPacketTypeV2::INITIAL -> initial_hdr: InitialPacket(outer) {
|
||||
outer.is_initial = True;
|
||||
outer.encrypted_offset = outer.offset() +
|
||||
self.initial_hdr.length.bytes_to_parse +
|
||||
self.initial_hdr.token_length.bytes_to_parse +
|
||||
self.initial_hdr.token_length.result_;
|
||||
outer.encrypted_offset = outer.offset() + self.initial_hdr.length.bytes_to_parse + self.initial_hdr.token_length.bytes_to_parse + self.initial_hdr.token_length.result_;
|
||||
outer.payload_length = self.initial_hdr.length.result_;
|
||||
}
|
||||
|
||||
LongPacketTypeV2::ZERO_RTT -> zerortt_hdr: ZeroRTTPacket(outer);
|
||||
LongPacketTypeV2::HANDSHAKE -> handshake_hdr: HandshakePacket(outer);
|
||||
LongPacketTypeV2::RETRY -> retry_hdr: RetryPacket(outer) {
|
||||
|
@ -302,9 +287,13 @@ public type LongHeaderPacket = unit {
|
|||
};
|
||||
|
||||
version: uint32;
|
||||
dest_conn_id_len: uint8 { self.server_conn_id_length = $$; }
|
||||
dest_conn_id_len: uint8 {
|
||||
self.server_conn_id_length = $$;
|
||||
}
|
||||
dest_conn_id: bytes &size=self.server_conn_id_length;
|
||||
src_conn_id_len: uint8 { self.client_conn_id_length = $$; }
|
||||
src_conn_id_len: uint8 {
|
||||
self.client_conn_id_length = $$;
|
||||
}
|
||||
src_conn_id: bytes &size=self.client_conn_id_length;
|
||||
|
||||
switch (self.version) {
|
||||
|
@ -407,7 +396,6 @@ type ConnectionClosePayload = unit(header: LongHeaderPacket) {
|
|||
reason_phrase: bytes &size=self.reason_phrase_length.result_;
|
||||
};
|
||||
|
||||
|
||||
##############
|
||||
# Long packets
|
||||
# Specific long packet type units
|
||||
|
@ -448,7 +436,6 @@ type HandshakePacket = unit(header: LongHeaderPacket) {
|
|||
payload: skip bytes &size=self.length.result_;
|
||||
};
|
||||
|
||||
|
||||
type RetryPacket = unit(header: LongHeaderPacket) {
|
||||
var header: LongHeaderPacket = header;
|
||||
var retry_token: bytes;
|
||||
|
@ -585,7 +572,6 @@ type Packet = unit(from_client: bool, context: Context&) {
|
|||
self.long_header.payload_length,
|
||||
from_client
|
||||
);
|
||||
|
||||
} else {
|
||||
context.server_cid_len = self.long_header.src_conn_id_len;
|
||||
context.client_cid_len = self.long_header.dest_conn_id_len;
|
||||
|
|
|
@ -12,11 +12,7 @@ const OPCODE_CLOSE = 0x08;
|
|||
const OPCODE_PING = 0x09;
|
||||
const OPCODE_PONG = 0x0a;
|
||||
|
||||
public function fast_unmask(
|
||||
masking_key_idx: uint64,
|
||||
masking_key: vector<uint8>,
|
||||
chunk: bytes
|
||||
): bytes &cxxname="hlt_websocket::WebSocket::fast_unmask";
|
||||
public function fast_unmask(masking_key_idx: uint64, masking_key: vector<uint8>, chunk: bytes): bytes &cxxname="hlt_websocket::WebSocket::fast_unmask";
|
||||
|
||||
type Frame = unit(m: Message) {
|
||||
var payload_len: uint64;
|
||||
|
@ -89,7 +85,6 @@ type CloseFrame = unit {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
public type Message = unit {
|
||||
# transient trickery
|
||||
var done: bool = False;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue