Skip to content
Snippets Groups Projects
Commit cbbd04cd authored by mtu's avatar mtu
Browse files

Make ASN1F_CHOICE more simple and readable

parent 79e2cdce
No related branches found
No related tags found
No related merge requests found
...@@ -400,16 +400,8 @@ class ASN1F_optional(ASN1F_field): ...@@ -400,16 +400,8 @@ class ASN1F_optional(ASN1F_field):
class ASN1F_CHOICE(ASN1F_field): class ASN1F_CHOICE(ASN1F_field):
""" """
Multiple types are allowed: ASN1_Packet, ASN1F_field and ASN1F_PACKET(), Multiple types are allowed: ASN1_Packet, ASN1F_field and ASN1F_PACKET(),
e.g. you could define ASN1F_CHOICE("qualifier", None, See layers/x509.py for examples.
X509_UserNotice,
ASN1F_X509_CPSuri)
or ASN1F_CHOICE("qualifier", None,
ASN1F_PACKET("index", dflt, X509_Pkt,
implicit_tag=0x82),
explicit_tag=0xa1)
Other ASN1F_field instances than ASN1F_PACKET instances must not be used. Other ASN1F_field instances than ASN1F_PACKET instances must not be used.
ASN1F_PACKET instances must not be mixed with other types.
self.instantiated_choices signals whether only such instances are present.
""" """
holds_packets = 1 holds_packets = 1
ASN1_tag = ASN1_Class_UNIVERSAL.ANY ASN1_tag = ASN1_Class_UNIVERSAL.ANY
...@@ -428,10 +420,9 @@ class ASN1F_CHOICE(ASN1F_field): ...@@ -428,10 +420,9 @@ class ASN1F_CHOICE(ASN1F_field):
self.default = default self.default = default
self.current_choice = None self.current_choice = None
self.choices = {} self.choices = {}
self.instantiated_choices = True self.pktchoices = {}
for p in args: for p in args:
if hasattr(p, "ASN1_root"): # should be ASN1_Packet if hasattr(p, "ASN1_root"): # should be ASN1_Packet
self.instantiated_choices = False
if hasattr(p.ASN1_root, "choices"): if hasattr(p.ASN1_root, "choices"):
for k,v in p.ASN1_root.choices.items(): for k,v in p.ASN1_root.choices.items():
self.choices[k] = v # ASN1F_CHOICE recursion self.choices[k] = v # ASN1F_CHOICE recursion
...@@ -439,18 +430,16 @@ class ASN1F_CHOICE(ASN1F_field): ...@@ -439,18 +430,16 @@ class ASN1F_CHOICE(ASN1F_field):
self.choices[p.ASN1_root.network_tag] = p self.choices[p.ASN1_root.network_tag] = p
elif hasattr(p, "ASN1_tag"): elif hasattr(p, "ASN1_tag"):
if type(p) is type: # should be ASN1F_field class if type(p) is type: # should be ASN1F_field class
self.instantiated_choices = False
self.choices[p.ASN1_tag] = p self.choices[p.ASN1_tag] = p
else: # should be ASN1F_PACKET instance else: # should be ASN1F_PACKET instance
self.choices[p.network_tag] = p self.choices[p.network_tag] = p
self.pktchoices[hash(p.cls)] = (p.implicit_tag, p.explicit_tag)
else: else:
raise ASN1_Error("ASN1F_CHOICE: no tag found for one field") raise ASN1_Error("ASN1F_CHOICE: no tag found for one field")
def m2i(self, pkt, s): def m2i(self, pkt, s):
""" """
First we have to retrieve the appropriate choice. First we have to retrieve the appropriate choice.
Then we extract the field/packet, according to this choice. Then we extract the field/packet, according to this choice.
In case the choice depends on implicit or explicit tags,
ASN1F_PACKET instance choices can be defined with the right tags.
""" """
if len(s) == 0: if len(s) == 0:
raise ASN1_Error("ASN1F_CHOICE: got empty string") raise ASN1_Error("ASN1F_CHOICE: got empty string")
...@@ -472,32 +461,16 @@ class ASN1F_CHOICE(ASN1F_field): ...@@ -472,32 +461,16 @@ class ASN1F_CHOICE(ASN1F_field):
return choice(self.name, "").m2i(pkt, s) return choice(self.name, "").m2i(pkt, s)
else: else:
# choice must be an ASN1F_PACKET instance here # choice must be an ASN1F_PACKET instance here
c,s = choice.m2i(pkt, s) return choice.m2i(pkt, s)
# dirty hack here: when c is an ASN1_Packet, its __dict__
# is controlled so we hide tags inside overload_fields
hcls = hash(choice.cls)
c.overload_fields[hcls] = {}
if hasattr(choice, "implicit_tag"):
c.overload_fields[hcls]["imp"] = choice.implicit_tag
else:
c.overload_fields[hcls]["imp"] = None
if hasattr(choice, "explicit_tag"):
c.overload_fields[hcls]["exp"] = choice.explicit_tag
else:
c.overload_fields[hcls]["exp"] = None
return c,s
def i2m(self, pkt, x): def i2m(self, pkt, x):
if x is None: if x is None:
s = "" s = ""
else: else:
s = str(x) s = str(x)
if self.instantiated_choices: if hash(type(x)) in self.pktchoices.keys():
cls = type(x) imp, exp = self.pktchoices[hash(type(x))]
if hash(cls) not in x.overload_fields: s = BER_tagging_enc(s, implicit_tag=imp,
raise ASN1_Error("ASN1F_CHOICE: could not encode object") explicit_tag=exp)
tags = x.overload_fields[hash(cls)]
s = BER_tagging_enc(s, implicit_tag=tags["imp"],
explicit_tag=tags["exp"])
return BER_tagging_enc(s, explicit_tag=self.explicit_tag) return BER_tagging_enc(s, explicit_tag=self.explicit_tag)
def randval(self): def randval(self):
return RandChoice(*map(lambda x:fuzz(x()), self.choice.values())) return RandChoice(*map(lambda x:fuzz(x()), self.choice.values()))
......
# X.509 unit tests % Tests for X.509 objects
# #
# Launch me with: # Launch me with:
# sudo bash test/run_tests -t test/x509.uts -F # sudo bash test/run_tests -t test/x509.uts -F
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment