Browse Source

Update pyasn1

pull/5122/head
Ruud 10 years ago
parent
commit
4e6ab1abf9
  1. 4
      libs/pyasn1/__init__.py
  2. 153
      libs/pyasn1/codec/ber/decoder.py
  3. 168
      libs/pyasn1/codec/ber/encoder.py
  4. 61
      libs/pyasn1/codec/cer/encoder.py
  5. 4
      libs/pyasn1/codec/der/decoder.py
  6. 12
      libs/pyasn1/codec/der/encoder.py
  7. 10
      libs/pyasn1/compat/binary.py
  8. 10
      libs/pyasn1/compat/iterfunc.py
  9. 65
      libs/pyasn1/debug.py
  10. 78
      libs/pyasn1/type/base.py
  11. 17
      libs/pyasn1/type/char.py
  12. 31
      libs/pyasn1/type/namedtype.py
  13. 12
      libs/pyasn1/type/namedval.py
  14. 10
      libs/pyasn1/type/tag.py
  15. 18
      libs/pyasn1/type/tagmap.py
  16. 230
      libs/pyasn1/type/univ.py
  17. 5
      libs/pyasn1/type/useful.py

4
libs/pyasn1/__init__.py

@ -1,8 +1,8 @@
import sys import sys
# http://www.python.org/dev/peps/pep-0396/ # http://www.python.org/dev/peps/pep-0396/
__version__ = '0.1.7' __version__ = '0.1.8'
if sys.version_info[:2] < (2, 4): if sys.version_info[:2] < (2, 4):
raise RuntimeError('PyASN1 requires Python 2.4 or later') raise RuntimeError('PyASN1 requires Python 2.4 or later')

153
libs/pyasn1/codec/ber/decoder.py

@ -1,7 +1,7 @@
# BER decoder # BER decoder
from pyasn1.type import tag, base, univ, char, useful, tagmap from pyasn1.type import tag, univ, char, useful, tagmap
from pyasn1.codec.ber import eoo from pyasn1.codec.ber import eoo
from pyasn1.compat.octets import oct2int, octs2ints, isOctetsType from pyasn1.compat.octets import oct2int, isOctetsType
from pyasn1 import debug, error from pyasn1 import debug, error
class AbstractDecoder: class AbstractDecoder:
@ -11,14 +11,14 @@ class AbstractDecoder:
raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,)) raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,))
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
length, state, decodeFun, substrateFun): length, state, decodeFun, substrateFun):
raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,))
class AbstractSimpleDecoder(AbstractDecoder): class AbstractSimpleDecoder(AbstractDecoder):
tagFormats = (tag.tagFormatSimple,) tagFormats = (tag.tagFormatSimple,)
def _createComponent(self, asn1Spec, tagSet, value=None): def _createComponent(self, asn1Spec, tagSet, value=None):
if tagSet[0][1] not in self.tagFormats: if tagSet[0][1] not in self.tagFormats:
raise error.PyAsn1Error('Invalid tag format %r for %r' % (tagSet[0], self.protoComponent,)) raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
if asn1Spec is None: if asn1Spec is None:
return self.protoComponent.clone(value, tagSet) return self.protoComponent.clone(value, tagSet)
elif value is None: elif value is None:
@ -30,17 +30,12 @@ class AbstractConstructedDecoder(AbstractDecoder):
tagFormats = (tag.tagFormatConstructed,) tagFormats = (tag.tagFormatConstructed,)
def _createComponent(self, asn1Spec, tagSet, value=None): def _createComponent(self, asn1Spec, tagSet, value=None):
if tagSet[0][1] not in self.tagFormats: if tagSet[0][1] not in self.tagFormats:
raise error.PyAsn1Error('Invalid tag format %r for %r' % (tagSet[0], self.protoComponent,)) raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
if asn1Spec is None: if asn1Spec is None:
return self.protoComponent.clone(tagSet) return self.protoComponent.clone(tagSet)
else: else:
return asn1Spec.clone() return asn1Spec.clone()
class EndOfOctetsDecoder(AbstractSimpleDecoder):
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
length, state, decodeFun, substrateFun):
return eoo.endOfOctets, substrate[length:]
class ExplicitTagDecoder(AbstractSimpleDecoder): class ExplicitTagDecoder(AbstractSimpleDecoder):
protoComponent = univ.Any('') protoComponent = univ.Any('')
tagFormats = (tag.tagFormatConstructed,) tagFormats = (tag.tagFormatConstructed,)
@ -63,7 +58,7 @@ class ExplicitTagDecoder(AbstractSimpleDecoder):
substrate, length substrate, length
) )
value, substrate = decodeFun(substrate, asn1Spec, tagSet, length) value, substrate = decodeFun(substrate, asn1Spec, tagSet, length)
terminator, substrate = decodeFun(substrate) terminator, substrate = decodeFun(substrate, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(terminator) and \ if eoo.endOfOctets.isSameTypeWith(terminator) and \
terminator == eoo.endOfOctets: terminator == eoo.endOfOctets:
return value, substrate return value, substrate
@ -129,14 +124,14 @@ class BitStringDecoder(AbstractSimpleDecoder):
'Trailing bits overflow %s' % trailingBits 'Trailing bits overflow %s' % trailingBits
) )
head = head[1:] head = head[1:]
lsb = p = 0; l = len(head)-1; b = () lsb = p = 0; l = len(head)-1; b = []
while p <= l: while p <= l:
if p == l: if p == l:
lsb = trailingBits lsb = trailingBits
j = 7 j = 7
o = oct2int(head[p]) o = oct2int(head[p])
while j >= lsb: while j >= lsb:
b = b + ((o>>j)&0x01,) b.append((o>>j)&0x01)
j = j - 1 j = j - 1
p = p + 1 p = p + 1
return self._createComponent(asn1Spec, tagSet, b), tail return self._createComponent(asn1Spec, tagSet, b), tail
@ -144,7 +139,7 @@ class BitStringDecoder(AbstractSimpleDecoder):
if substrateFun: if substrateFun:
return substrateFun(r, substrate, length) return substrateFun(r, substrate, length)
while head: while head:
component, head = decodeFun(head) component, head = decodeFun(head, self.protoComponent)
r = r + component r = r + component
return r, tail return r, tail
@ -154,7 +149,8 @@ class BitStringDecoder(AbstractSimpleDecoder):
if substrateFun: if substrateFun:
return substrateFun(r, substrate, length) return substrateFun(r, substrate, length)
while substrate: while substrate:
component, substrate = decodeFun(substrate) component, substrate = decodeFun(substrate, self.protoComponent,
allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \ if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets: component == eoo.endOfOctets:
break break
@ -177,7 +173,7 @@ class OctetStringDecoder(AbstractSimpleDecoder):
if substrateFun: if substrateFun:
return substrateFun(r, substrate, length) return substrateFun(r, substrate, length)
while head: while head:
component, head = decodeFun(head) component, head = decodeFun(head, self.protoComponent)
r = r + component r = r + component
return r, tail return r, tail
@ -187,7 +183,8 @@ class OctetStringDecoder(AbstractSimpleDecoder):
if substrateFun: if substrateFun:
return substrateFun(r, substrate, length) return substrateFun(r, substrate, length)
while substrate: while substrate:
component, substrate = decodeFun(substrate) component, substrate = decodeFun(substrate, self.protoComponent,
allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \ if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets: component == eoo.endOfOctets:
break break
@ -216,20 +213,14 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
if not head: if not head:
raise error.PyAsn1Error('Empty substrate') raise error.PyAsn1Error('Empty substrate')
# Get the first subid oid = ()
subId = oct2int(head[0]) index = 0
oid = divmod(subId, 40)
index = 1
substrateLen = len(head) substrateLen = len(head)
while index < substrateLen: while index < substrateLen:
subId = oct2int(head[index]) subId = oct2int(head[index])
index = index + 1 index += 1
if subId == 128: if subId < 128:
# ASN.1 spec forbids leading zeros (0x80) in sub-ID OID oid = oid + (subId,)
# encoding, tolerating it opens a vulnerability.
# See http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf page 7
raise error.PyAsn1Error('Invalid leading 0x80 in sub-OID')
elif subId > 128: elif subId > 128:
# Construct subid from a number of octets # Construct subid from a number of octets
nextSubId = subId nextSubId = subId
@ -239,11 +230,27 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
if index >= substrateLen: if index >= substrateLen:
raise error.SubstrateUnderrunError( raise error.SubstrateUnderrunError(
'Short substrate for sub-OID past %s' % (oid,) 'Short substrate for sub-OID past %s' % (oid,)
) )
nextSubId = oct2int(head[index]) nextSubId = oct2int(head[index])
index = index + 1 index += 1
subId = (subId << 7) + nextSubId oid = oid + ((subId << 7) + nextSubId,)
oid = oid + (subId,) elif subId == 128:
# ASN.1 spec forbids leading zeros (0x80) in OID
# encoding, tolerating it opens a vulnerability. See
# http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf
# page 7
raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
# Decode two leading arcs
if 0 <= oid[0] <= 39:
oid = (0,) + oid
elif 40 <= oid[0] <= 79:
oid = (1, oid[0]-40) + oid[1:]
elif oid[0] >= 80:
oid = (2, oid[0]-80) + oid[1:]
else:
raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0])
return self._createComponent(asn1Spec, tagSet, oid), tail return self._createComponent(asn1Spec, tagSet, oid), tail
class RealDecoder(AbstractSimpleDecoder): class RealDecoder(AbstractSimpleDecoder):
@ -254,10 +261,13 @@ class RealDecoder(AbstractSimpleDecoder):
if not head: if not head:
return self._createComponent(asn1Spec, tagSet, 0.0), tail return self._createComponent(asn1Spec, tagSet, 0.0), tail
fo = oct2int(head[0]); head = head[1:] fo = oct2int(head[0]); head = head[1:]
if fo & 0x80: # binary enoding if fo & 0x80: # binary encoding
if not head:
raise error.PyAsn1Error("Incomplete floating-point value")
n = (fo & 0x03) + 1 n = (fo & 0x03) + 1
if n == 4: if n == 4:
n = oct2int(head[0]) n = oct2int(head[0])
head = head[1:]
eo, head = head[:n], head[n:] eo, head = head[:n], head[n:]
if not eo or not head: if not eo or not head:
raise error.PyAsn1Error('Real exponent screwed') raise error.PyAsn1Error('Real exponent screwed')
@ -266,6 +276,13 @@ class RealDecoder(AbstractSimpleDecoder):
e <<= 8 e <<= 8
e |= oct2int(eo[0]) e |= oct2int(eo[0])
eo = eo[1:] eo = eo[1:]
b = fo >> 4 & 0x03 # base bits
if b > 2:
raise error.PyAsn1Error('Illegal Real base')
if b == 1: # encbase = 8
e *= 3
elif b == 2: # encbase = 16
e *= 4
p = 0 p = 0
while head: # value while head: # value
p <<= 8 p <<= 8
@ -273,10 +290,14 @@ class RealDecoder(AbstractSimpleDecoder):
head = head[1:] head = head[1:]
if fo & 0x40: # sign bit if fo & 0x40: # sign bit
p = -p p = -p
sf = fo >> 2 & 0x03 # scale bits
p *= 2**sf
value = (p, 2, e) value = (p, 2, e)
elif fo & 0x40: # infinite value elif fo & 0x40: # infinite value
value = fo & 0x01 and '-inf' or 'inf' value = fo & 0x01 and '-inf' or 'inf'
elif fo & 0xc0 == 0: # character encoding elif fo & 0xc0 == 0: # character encoding
if not head:
raise error.PyAsn1Error("Incomplete floating-point value")
try: try:
if fo & 0x3 == 0x1: # NR1 if fo & 0x3 == 0x1: # NR1
value = (int(head), 10, 0) value = (int(head), 10, 0)
@ -336,7 +357,7 @@ class SequenceDecoder(AbstractConstructedDecoder):
idx = 0 idx = 0
while substrate: while substrate:
asn1Spec = self._getComponentTagMap(r, idx) asn1Spec = self._getComponentTagMap(r, idx)
component, substrate = decodeFun(substrate, asn1Spec) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \ if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets: component == eoo.endOfOctets:
break break
@ -378,7 +399,7 @@ class SequenceOfDecoder(AbstractConstructedDecoder):
asn1Spec = r.getComponentType() asn1Spec = r.getComponentType()
idx = 0 idx = 0
while substrate: while substrate:
component, substrate = decodeFun(substrate, asn1Spec) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \ if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets: component == eoo.endOfOctets:
break break
@ -437,7 +458,8 @@ class ChoiceDecoder(AbstractConstructedDecoder):
return substrateFun(r, substrate, length) return substrateFun(r, substrate, length)
if r.getTagSet() == tagSet: # explicitly tagged Choice if r.getTagSet() == tagSet: # explicitly tagged Choice
component, substrate = decodeFun(substrate, r.getComponentTagMap()) component, substrate = decodeFun(substrate, r.getComponentTagMap())
eooMarker, substrate = decodeFun(substrate) # eat up EOO marker # eat up EOO marker
eooMarker, substrate = decodeFun(substrate, allowEoo=True)
if not eoo.endOfOctets.isSameTypeWith(eooMarker) or \ if not eoo.endOfOctets.isSameTypeWith(eooMarker) or \
eooMarker != eoo.endOfOctets: eooMarker != eoo.endOfOctets:
raise error.PyAsn1Error('No EOO seen before substrate ends') raise error.PyAsn1Error('No EOO seen before substrate ends')
@ -485,7 +507,7 @@ class AnyDecoder(AbstractSimpleDecoder):
if substrateFun: if substrateFun:
return substrateFun(r, substrate, length) return substrateFun(r, substrate, length)
while substrate: while substrate:
component, substrate = decodeFun(substrate, asn1Spec) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \ if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets: component == eoo.endOfOctets:
break break
@ -521,13 +543,14 @@ class BMPStringDecoder(OctetStringDecoder):
protoComponent = char.BMPString() protoComponent = char.BMPString()
# "useful" types # "useful" types
class ObjectDescriptorDecoder(OctetStringDecoder):
protoComponent = useful.ObjectDescriptor()
class GeneralizedTimeDecoder(OctetStringDecoder): class GeneralizedTimeDecoder(OctetStringDecoder):
protoComponent = useful.GeneralizedTime() protoComponent = useful.GeneralizedTime()
class UTCTimeDecoder(OctetStringDecoder): class UTCTimeDecoder(OctetStringDecoder):
protoComponent = useful.UTCTime() protoComponent = useful.UTCTime()
tagMap = { tagMap = {
eoo.endOfOctets.tagSet: EndOfOctetsDecoder(),
univ.Integer.tagSet: IntegerDecoder(), univ.Integer.tagSet: IntegerDecoder(),
univ.Boolean.tagSet: BooleanDecoder(), univ.Boolean.tagSet: BooleanDecoder(),
univ.BitString.tagSet: BitStringDecoder(), univ.BitString.tagSet: BitStringDecoder(),
@ -552,9 +575,10 @@ tagMap = {
char.UniversalString.tagSet: UniversalStringDecoder(), char.UniversalString.tagSet: UniversalStringDecoder(),
char.BMPString.tagSet: BMPStringDecoder(), char.BMPString.tagSet: BMPStringDecoder(),
# useful types # useful types
useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(),
useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(), useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(),
useful.UTCTime.tagSet: UTCTimeDecoder() useful.UTCTime.tagSet: UTCTimeDecoder()
} }
# Type-to-codec map for ambiguous ASN.1 types # Type-to-codec map for ambiguous ASN.1 types
typeMap = { typeMap = {
@ -564,7 +588,7 @@ typeMap = {
univ.SequenceOf.typeId: SequenceOfDecoder(), univ.SequenceOf.typeId: SequenceOfDecoder(),
univ.Choice.typeId: ChoiceDecoder(), univ.Choice.typeId: ChoiceDecoder(),
univ.Any.typeId: AnyDecoder() univ.Any.typeId: AnyDecoder()
} }
( stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec, ( stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec,
stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue, stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue,
@ -574,23 +598,22 @@ class Decoder:
defaultErrorState = stErrorCondition defaultErrorState = stErrorCondition
# defaultErrorState = stDumpRawValue # defaultErrorState = stDumpRawValue
defaultRawDecoder = AnyDecoder() defaultRawDecoder = AnyDecoder()
supportIndefLength = True
def __init__(self, tagMap, typeMap={}): def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap self.__tagMap = tagMap
self.__typeMap = typeMap self.__typeMap = typeMap
self.__endOfOctetsTagSet = eoo.endOfOctets.getTagSet()
# Tag & TagSet objects caches # Tag & TagSet objects caches
self.__tagCache = {} self.__tagCache = {}
self.__tagSetCache = {} self.__tagSetCache = {}
def __call__(self, substrate, asn1Spec=None, tagSet=None, def __call__(self, substrate, asn1Spec=None, tagSet=None,
length=None, state=stDecodeTag, recursiveFlag=1, length=None, state=stDecodeTag, recursiveFlag=1,
substrateFun=None): substrateFun=None, allowEoo=False):
if debug.logger & debug.flagDecoder: if debug.logger & debug.flagDecoder:
debug.logger('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate))) debug.logger('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate)))
fullSubstrate = substrate fullSubstrate = substrate
while state != stStop: while state != stStop:
if state == stDecodeTag: if state == stDecodeTag:
# Decode tag
if not substrate: if not substrate:
raise error.SubstrateUnderrunError( raise error.SubstrateUnderrunError(
'Short octet stream on tag decoding' 'Short octet stream on tag decoding'
@ -598,13 +621,25 @@ class Decoder:
if not isOctetsType(substrate) and \ if not isOctetsType(substrate) and \
not isinstance(substrate, univ.OctetString): not isinstance(substrate, univ.OctetString):
raise error.PyAsn1Error('Bad octet stream type') raise error.PyAsn1Error('Bad octet stream type')
# Decode tag
firstOctet = substrate[0] firstOctet = substrate[0]
substrate = substrate[1:] substrate = substrate[1:]
if firstOctet in self.__tagCache: if firstOctet in self.__tagCache:
lastTag = self.__tagCache[firstOctet] lastTag = self.__tagCache[firstOctet]
else: else:
t = oct2int(firstOctet) t = oct2int(firstOctet)
# Look for end-of-octets sentinel
if t == 0:
if substrate and oct2int(substrate[0]) == 0:
if allowEoo and self.supportIndefLength:
debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets sentinel found')
value, substrate = eoo.endOfOctets, substrate[1:]
state = stStop
continue
else:
raise error.PyAsn1Error('Unexpected end-of-contents sentinel')
else:
raise error.PyAsn1Error('Zero tag encountered')
tagClass = t&0xC0 tagClass = t&0xC0
tagFormat = t&0x20 tagFormat = t&0x20
tagId = t&0x1F tagId = t&0x1F
@ -622,7 +657,7 @@ class Decoder:
break break
lastTag = tag.Tag( lastTag = tag.Tag(
tagClass=tagClass, tagFormat=tagFormat, tagId=tagId tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
) )
if tagId < 31: if tagId < 31:
# cache short tags # cache short tags
self.__tagCache[firstOctet] = lastTag self.__tagCache[firstOctet] = lastTag
@ -637,13 +672,13 @@ class Decoder:
else: else:
tagSet = lastTag + tagSet tagSet = lastTag + tagSet
state = stDecodeLength state = stDecodeLength
debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %r, decoding length' % tagSet) debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %s, decoding length' % tagSet)
if state == stDecodeLength: if state == stDecodeLength:
# Decode length # Decode length
if not substrate: if not substrate:
raise error.SubstrateUnderrunError( raise error.SubstrateUnderrunError(
'Short octet stream on length decoding' 'Short octet stream on length decoding'
) )
firstOctet = oct2int(substrate[0]) firstOctet = oct2int(substrate[0])
if firstOctet == 128: if firstOctet == 128:
size = 1 size = 1
@ -670,6 +705,8 @@ class Decoder:
raise error.SubstrateUnderrunError( raise error.SubstrateUnderrunError(
'%d-octet short' % (length - len(substrate)) '%d-octet short' % (length - len(substrate))
) )
if length == -1 and not self.supportIndefLength:
error.PyAsn1Error('Indefinite length encoding not supported by this codec')
state = stGetValueDecoder state = stGetValueDecoder
debug.logger and debug.logger & debug.flagDecoder and debug.logger('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length]))) debug.logger and debug.logger & debug.flagDecoder and debug.logger('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length])))
if state == stGetValueDecoder: if state == stGetValueDecoder:
@ -722,12 +759,12 @@ class Decoder:
if debug.logger and debug.logger & debug.flagDecoder: if debug.logger and debug.logger & debug.flagDecoder:
debug.logger('candidate ASN.1 spec is a map of:') debug.logger('candidate ASN.1 spec is a map of:')
for t, v in asn1Spec.getPosMap().items(): for t, v in asn1Spec.getPosMap().items():
debug.logger(' %r -> %s' % (t, v.__class__.__name__)) debug.logger(' %s -> %s' % (t, v.__class__.__name__))
if asn1Spec.getNegMap(): if asn1Spec.getNegMap():
debug.logger('but neither of: ') debug.logger('but neither of: ')
for i in asn1Spec.getNegMap().items(): for t, v in asn1Spec.getNegMap().items():
debug.logger(' %r -> %s' % (t, v.__class__.__name__)) debug.logger(' %s -> %s' % (t, v.__class__.__name__))
debug.logger('new candidate ASN.1 spec is %s, chosen by %r' % (__chosenSpec is None and '<none>' or __chosenSpec.__class__.__name__, tagSet)) debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (__chosenSpec is None and '<none>' or __chosenSpec.prettyPrintType(), tagSet))
else: else:
__chosenSpec = asn1Spec __chosenSpec = asn1Spec
debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
@ -745,7 +782,7 @@ class Decoder:
elif baseTagSet in self.__tagMap: elif baseTagSet in self.__tagMap:
# base type or tagged subtype # base type or tagged subtype
concreteDecoder = self.__tagMap[baseTagSet] concreteDecoder = self.__tagMap[baseTagSet]
debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %r' % (baseTagSet,)) debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %s' % (baseTagSet,))
else: else:
concreteDecoder = None concreteDecoder = None
if concreteDecoder: if concreteDecoder:
@ -753,10 +790,6 @@ class Decoder:
state = stDecodeValue state = stDecodeValue
else: else:
state = stTryAsExplicitTag state = stTryAsExplicitTag
elif tagSet == self.__endOfOctetsTagSet:
concreteDecoder = self.__tagMap[tagSet]
state = stDecodeValue
debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets found')
else: else:
concreteDecoder = None concreteDecoder = None
state = stTryAsExplicitTag state = stTryAsExplicitTag
@ -795,8 +828,8 @@ class Decoder:
debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>')) debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>'))
if state == stErrorCondition: if state == stErrorCondition:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'%r not in asn1Spec: %r' % (tagSet, asn1Spec) '%s not in asn1Spec: %s' % (tagSet, asn1Spec)
) )
if debug.logger and debug.logger & debug.flagDecoder: if debug.logger and debug.logger & debug.flagDecoder:
debug.scope.pop() debug.scope.pop()
debug.logger('decoder left scope %s, call completed' % debug.scope) debug.logger('decoder left scope %s, call completed' % debug.scope)

168
libs/pyasn1/codec/ber/encoder.py

@ -114,13 +114,17 @@ class IntegerEncoder(AbstractItemEncoder):
class BitStringEncoder(AbstractItemEncoder): class BitStringEncoder(AbstractItemEncoder):
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
if not maxChunkSize or len(value) <= maxChunkSize*8: if not maxChunkSize or len(value) <= maxChunkSize*8:
r = {}; l = len(value); p = 0; j = 7 out_len = (len(value) + 7) // 8
while p < l: out_list = out_len * [0]
i, j = divmod(p, 8) j = 7
r[i] = r.get(i,0) | value[p]<<(7-j) i = -1
p = p + 1 for val in value:
keys = list(r); keys.sort() j += 1
return int2oct(7-j) + ints2octs([r[k] for k in keys]), 0 if j == 8:
i += 1
j = 0
out_list[i] = out_list[i] | val << (7-j)
return int2oct(7-j) + ints2octs(out_list), 0
else: else:
pos = 0; substrate = null pos = 0; substrate = null
while 1: while 1:
@ -156,47 +160,98 @@ class ObjectIdentifierEncoder(AbstractItemEncoder):
precomputedValues = { precomputedValues = {
(1, 3, 6, 1, 2): (43, 6, 1, 2), (1, 3, 6, 1, 2): (43, 6, 1, 2),
(1, 3, 6, 1, 4): (43, 6, 1, 4) (1, 3, 6, 1, 4): (43, 6, 1, 4)
} }
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
oid = value.asTuple() oid = value.asTuple()
if oid[:5] in self.precomputedValues: if oid[:5] in self.precomputedValues:
octets = self.precomputedValues[oid[:5]] octets = self.precomputedValues[oid[:5]]
index = 5 oid = oid[5:]
else: else:
if len(oid) < 2: if len(oid) < 2:
raise error.PyAsn1Error('Short OID %s' % (value,)) raise error.PyAsn1Error('Short OID %s' % (value,))
octets = ()
# Build the first twos # Build the first twos
if oid[0] > 6 or oid[1] > 39 or oid[0] == 6 and oid[1] > 15: if oid[0] == 0 and 0 <= oid[1] <= 39:
oid = (oid[1],) + oid[2:]
elif oid[0] == 1 and 0 <= oid[1] <= 39:
oid = (oid[1] + 40,) + oid[2:]
elif oid[0] == 2:
oid = (oid[1] + 80,) + oid[2:]
else:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Initial sub-ID overflow %s in OID %s' % (oid[:2], value) 'Impossible initial arcs %s at %s' % (oid[:2], value)
) )
octets = (oid[0] * 40 + oid[1],)
index = 2
# Cycle through subids # Cycle through subIds
for subid in oid[index:]: for subId in oid:
if subid > -1 and subid < 128: if subId > -1 and subId < 128:
# Optimize for the common case # Optimize for the common case
octets = octets + (subid & 0x7f,) octets = octets + (subId & 0x7f,)
elif subid < 0 or subid > 0xFFFFFFFF: elif subId < 0:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'SubId overflow %s in %s' % (subid, value) 'Negative OID arc %s at %s' % (subId, value)
) )
else: else:
# Pack large Sub-Object IDs # Pack large Sub-Object IDs
res = (subid & 0x7f,) res = (subId & 0x7f,)
subid = subid >> 7 subId = subId >> 7
while subid > 0: while subId > 0:
res = (0x80 | (subid & 0x7f),) + res res = (0x80 | (subId & 0x7f),) + res
subid = subid >> 7 subId = subId >> 7
# Add packed Sub-Object ID to resulted Object ID # Add packed Sub-Object ID to resulted Object ID
octets += res octets += res
return ints2octs(octets), 0 return ints2octs(octets), 0
class RealEncoder(AbstractItemEncoder): class RealEncoder(AbstractItemEncoder):
supportIndefLenMode = 0 supportIndefLenMode = 0
binEncBase = 2 # set to None to choose encoding base automatically
def _dropFloatingPoint(self, m, encbase, e):
ms, es = 1, 1
if m < 0:
ms = -1 # mantissa sign
if e < 0:
es = -1 # exponenta sign
m *= ms
if encbase == 8:
m = m*2**(abs(e) % 3 * es)
e = abs(e) // 3 * es
elif encbase == 16:
m = m*2**(abs(e) % 4 * es)
e = abs(e) // 4 * es
while 1:
if int(m) != m:
m *= encbase
e -= 1
continue
break
return ms, int(m), encbase, e
def _chooseEncBase(self, value):
m, b, e = value
base = [2, 8, 16]
if value.binEncBase in base:
return self._dropFloatingPoint(m, value.binEncBase, e)
elif self.binEncBase in base:
return self._dropFloatingPoint(m, self.binEncBase, e)
# auto choosing base 2/8/16
mantissa = [m, m, m]
exponenta = [e, e, e]
encbase = 2
e = float('inf')
for i in range(3):
sign, mantissa[i], base[i], exponenta[i] = \
self._dropFloatingPoint(mantissa[i], base[i], exponenta[i])
if abs(exponenta[i]) < abs(e) or \
(abs(exponenta[i]) == abs(e) and mantissa[i] < m):
e = exponenta[i]
m = int(mantissa[i])
encbase = base[i]
return sign, m, encbase, e
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
if value.isPlusInfinity(): if value.isPlusInfinity():
return int2oct(0x40), 0 return int2oct(0x40), 0
@ -208,22 +263,43 @@ class RealEncoder(AbstractItemEncoder):
if b == 10: if b == 10:
return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0 return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0
elif b == 2: elif b == 2:
fo = 0x80 # binary enoding fo = 0x80 # binary encoding
if m < 0: ms, m, encbase, e = self._chooseEncBase(value)
fo = fo | 0x40 # sign bit if ms < 0: # mantissa sign
m = -m fo = fo | 0x40 # sign bit
while int(m) != m: # drop floating point # exponenta & mantissa normalization
m *= 2 if encbase == 2:
e -= 1 while m & 0x1 == 0:
while m & 0x1 == 0: # mantissa normalization m >>= 1
e += 1
elif encbase == 8:
while m & 0x7 == 0:
m >>= 3
e += 1
fo |= 0x10
else: # encbase = 16
while m & 0xf == 0:
m >>= 4
e += 1
fo |= 0x20
sf = 0 # scale factor
while m & 0x1 == 0:
m >>= 1 m >>= 1
e += 1 sf += 1
if sf > 3:
raise error.PyAsn1Error('Scale factor overflow') # bug if raised
fo |= sf << 2
eo = null eo = null
while e not in (0, -1): if e == 0 or e == -1:
eo = int2oct(e&0xff) + eo eo = int2oct(e&0xff)
e >>= 8 else:
if e == 0 and eo and oct2int(eo[0]) & 0x80: while e not in (0, -1):
eo = int2oct(0) + eo eo = int2oct(e&0xff) + eo
e >>= 8
if e == 0 and eo and oct2int(eo[0]) & 0x80:
eo = int2oct(0) + eo
if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
eo = int2oct(0xff) + eo
n = len(eo) n = len(eo)
if n > 0xff: if n > 0xff:
raise error.PyAsn1Error('Real exponent overflow') raise error.PyAsn1Error('Real exponent overflow')
@ -235,7 +311,7 @@ class RealEncoder(AbstractItemEncoder):
fo |= 2 fo |= 2
else: else:
fo |= 3 fo |= 3
eo = int2oct(n//0xff+1) + eo eo = int2oct(n&0xff) + eo
po = null po = null
while m: while m:
po = int2oct(m&0xff) + po po = int2oct(m&0xff) + po
@ -308,6 +384,7 @@ tagMap = {
char.UniversalString.tagSet: OctetStringEncoder(), char.UniversalString.tagSet: OctetStringEncoder(),
char.BMPString.tagSet: OctetStringEncoder(), char.BMPString.tagSet: OctetStringEncoder(),
# useful types # useful types
useful.ObjectDescriptor.tagSet: OctetStringEncoder(),
useful.GeneralizedTime.tagSet: OctetStringEncoder(), useful.GeneralizedTime.tagSet: OctetStringEncoder(),
useful.UTCTime.tagSet: OctetStringEncoder() useful.UTCTime.tagSet: OctetStringEncoder()
} }
@ -323,12 +400,15 @@ typeMap = {
} }
class Encoder: class Encoder:
supportIndefLength = True
def __init__(self, tagMap, typeMap={}): def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap self.__tagMap = tagMap
self.__typeMap = typeMap self.__typeMap = typeMap
def __call__(self, value, defMode=1, maxChunkSize=0): def __call__(self, value, defMode=True, maxChunkSize=0):
debug.logger & debug.flagEncoder and debug.logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.__class__.__name__, value.prettyPrint())) if not defMode and not self.supportIndefLength:
raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
debug.logger & debug.flagEncoder and debug.logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint()))
tagSet = value.getTagSet() tagSet = value.getTagSet()
if len(tagSet) > 1: if len(tagSet) > 1:
concreteEncoder = explicitlyTaggedItemEncoder concreteEncoder = explicitlyTaggedItemEncoder
@ -343,7 +423,7 @@ class Encoder:
concreteEncoder = self.__tagMap[tagSet] concreteEncoder = self.__tagMap[tagSet]
else: else:
raise Error('No encoder for %s' % (value,)) raise Error('No encoder for %s' % (value,))
debug.logger & debug.flagEncoder and debug.logger('using value codec %s chosen by %r' % (concreteEncoder.__class__.__name__, tagSet)) debug.logger & debug.flagEncoder and debug.logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
substrate = concreteEncoder.encode( substrate = concreteEncoder.encode(
self, value, defMode, maxChunkSize self, value, defMode, maxChunkSize
) )

61
libs/pyasn1/codec/cer/encoder.py

@ -1,7 +1,9 @@
# CER encoder # CER encoder
from pyasn1.type import univ from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1.codec.ber import encoder from pyasn1.codec.ber import encoder
from pyasn1.compat.octets import int2oct, null from pyasn1.compat.octets import int2oct, str2octs, null
from pyasn1 import error
class BooleanEncoder(encoder.IntegerEncoder): class BooleanEncoder(encoder.IntegerEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize): def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
@ -15,18 +17,56 @@ class BitStringEncoder(encoder.BitStringEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize): def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
return encoder.BitStringEncoder.encodeValue( return encoder.BitStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000 self, encodeFun, client, defMode, 1000
) )
class OctetStringEncoder(encoder.OctetStringEncoder): class OctetStringEncoder(encoder.OctetStringEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize): def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
return encoder.OctetStringEncoder.encodeValue( return encoder.OctetStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000 self, encodeFun, client, defMode, 1000
) )
class RealEncoder(encoder.RealEncoder):
def _chooseEncBase(self, value):
m, b, e = value
return self._dropFloatingPoint(m, b, e)
# specialized RealEncoder here
# specialized GeneralStringEncoder here # specialized GeneralStringEncoder here
# specialized GeneralizedTimeEncoder here
# specialized UTCTimeEncoder here class GeneralizedTimeEncoder(OctetStringEncoder):
zchar = str2octs('Z')
pluschar = str2octs('+')
minuschar = str2octs('-')
zero = str2octs('0')
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
octets = client.asOctets()
# This breaks too many existing data items
# if '.' not in octets:
# raise error.PyAsn1Error('Format must include fraction of second: %r' % octets)
if len(octets) < 15:
raise error.PyAsn1Error('Bad UTC time length: %r' % octets)
if self.pluschar in octets or self.minuschar in octets:
raise error.PyAsn1Error('Must be UTC time: %r' % octets)
if octets[-1] != self.zchar[0]:
raise error.PyAsn1Error('Missing timezone specifier: %r' % octets)
return encoder.OctetStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000
)
class UTCTimeEncoder(encoder.OctetStringEncoder):
zchar = str2octs('Z')
pluschar = str2octs('+')
minuschar = str2octs('-')
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
octets = client.asOctets()
if self.pluschar in octets or self.minuschar in octets:
raise error.PyAsn1Error('Must be UTC time: %r' % octets)
if octets and octets[-1] != self.zchar[0]:
client = client.clone(octets + self.zchar)
if len(client) != 13:
raise error.PyAsn1Error('Bad UTC time length: %r' % client)
return encoder.OctetStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000
)
class SetOfEncoder(encoder.SequenceOfEncoder): class SetOfEncoder(encoder.SequenceOfEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize): def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
@ -69,17 +109,20 @@ tagMap.update({
univ.Boolean.tagSet: BooleanEncoder(), univ.Boolean.tagSet: BooleanEncoder(),
univ.BitString.tagSet: BitStringEncoder(), univ.BitString.tagSet: BitStringEncoder(),
univ.OctetString.tagSet: OctetStringEncoder(), univ.OctetString.tagSet: OctetStringEncoder(),
univ.Real.tagSet: RealEncoder(),
useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(),
useful.UTCTime.tagSet: UTCTimeEncoder(),
univ.SetOf().tagSet: SetOfEncoder() # conflcts with Set univ.SetOf().tagSet: SetOfEncoder() # conflcts with Set
}) })
typeMap = encoder.typeMap.copy() typeMap = encoder.typeMap.copy()
typeMap.update({ typeMap.update({
univ.Set.typeId: SetOfEncoder(), univ.Set.typeId: SetOfEncoder(),
univ.SetOf.typeId: SetOfEncoder() univ.SetOf.typeId: SetOfEncoder()
}) })
class Encoder(encoder.Encoder): class Encoder(encoder.Encoder):
def __call__(self, client, defMode=0, maxChunkSize=0): def __call__(self, client, defMode=False, maxChunkSize=0):
return encoder.Encoder.__call__(self, client, defMode, maxChunkSize) return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
encode = Encoder(tagMap, typeMap) encode = Encoder(tagMap, typeMap)

4
libs/pyasn1/codec/der/decoder.py

@ -1,9 +1,9 @@
# DER decoder # DER decoder
from pyasn1.type import univ
from pyasn1.codec.cer import decoder from pyasn1.codec.cer import decoder
tagMap = decoder.tagMap tagMap = decoder.tagMap
typeMap = decoder.typeMap typeMap = decoder.typeMap
Decoder = decoder.Decoder class Decoder(decoder.Decoder):
supportIndefLength = False
decode = Decoder(tagMap, typeMap) decode = Decoder(tagMap, typeMap)

12
libs/pyasn1/codec/der/encoder.py

@ -1,6 +1,7 @@
# DER encoder # DER encoder
from pyasn1.type import univ from pyasn1.type import univ
from pyasn1.codec.cer import encoder from pyasn1.codec.cer import encoder
from pyasn1 import error
class SetOfEncoder(encoder.SetOfEncoder): class SetOfEncoder(encoder.SetOfEncoder):
def _cmpSetComponents(self, c1, c2): def _cmpSetComponents(self, c1, c2):
@ -12,17 +13,20 @@ class SetOfEncoder(encoder.SetOfEncoder):
tagMap = encoder.tagMap.copy() tagMap = encoder.tagMap.copy()
tagMap.update({ tagMap.update({
# Overload CER encodrs with BER ones (a bit hackerish XXX) # Overload CER encoders with BER ones (a bit hackerish XXX)
univ.BitString.tagSet: encoder.encoder.BitStringEncoder(), univ.BitString.tagSet: encoder.encoder.BitStringEncoder(),
univ.OctetString.tagSet: encoder.encoder.OctetStringEncoder(), univ.OctetString.tagSet: encoder.encoder.OctetStringEncoder(),
# Set & SetOf have same tags # Set & SetOf have same tags
univ.SetOf().tagSet: SetOfEncoder() univ.SetOf().tagSet: SetOfEncoder()
}) })
typeMap = encoder.typeMap typeMap = encoder.typeMap
class Encoder(encoder.Encoder): class Encoder(encoder.Encoder):
def __call__(self, client, defMode=1, maxChunkSize=0): supportIndefLength = False
def __call__(self, client, defMode=True, maxChunkSize=0):
if not defMode:
raise error.PyAsn1Error('DER forbids indefinite length mode')
return encoder.Encoder.__call__(self, client, defMode, maxChunkSize) return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
encode = Encoder(tagMap, typeMap) encode = Encoder(tagMap, typeMap)

10
libs/pyasn1/compat/binary.py

@ -0,0 +1,10 @@
from sys import version_info
if version_info[0:2] < (2, 6):
def bin(x):
if x <= 1:
return '0b'+str(x)
else:
return bin(x>>1) + str(x&1)
else:
bin = bin

10
libs/pyasn1/compat/iterfunc.py

@ -0,0 +1,10 @@
from sys import version_info
if version_info[0] <= 2 and version_info[1] <= 4:
def all(iterable):
for element in iterable:
if not element:
return False
return True
else:
all = all

65
libs/pyasn1/debug.py

@ -1,4 +1,5 @@
import sys import time
import logging
from pyasn1.compat.octets import octs2ints from pyasn1.compat.octets import octs2ints
from pyasn1 import error from pyasn1 import error
from pyasn1 import __version__ from pyasn1 import __version__
@ -14,23 +15,67 @@ flagMap = {
'all': flagAll 'all': flagAll
} }
class Printer:
def __init__(self, logger=None, handler=None, formatter=None):
if logger is None:
logger = logging.getLogger('pyasn1')
logger.setLevel(logging.DEBUG)
if handler is None:
handler = logging.StreamHandler()
if formatter is None:
formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
self.__logger = logger
def __call__(self, msg): self.__logger.debug(msg)
def __str__(self): return '<python built-in logging>'
if hasattr(logging, 'NullHandler'):
NullHandler = logging.NullHandler
else:
# Python 2.6 and older
class NullHandler(logging.Handler):
def emit(self, record):
pass
class Debug: class Debug:
defaultPrinter = sys.stderr.write defaultPrinter = None
def __init__(self, *flags): def __init__(self, *flags, **options):
self._flags = flagNone self._flags = flagNone
self._printer = self.defaultPrinter if options.get('printer') is not None:
self._printer = options.get('printer')
elif self.defaultPrinter is not None:
self._printer = self.defaultPrinter
if 'loggerName' in options:
# route our logs to parent logger
self._printer = Printer(
logger=logging.getLogger(options['loggerName']),
handler=NullHandler()
)
else:
self._printer = Printer()
self('running pyasn1 version %s' % __version__) self('running pyasn1 version %s' % __version__)
for f in flags: for f in flags:
if f not in flagMap: inverse = f and f[0] in ('!', '~')
raise error.PyAsn1Error('bad debug flag %s' % (f,)) if inverse:
self._flags = self._flags | flagMap[f] f = f[1:]
self('debug category \'%s\' enabled' % f) try:
if inverse:
self._flags &= ~flagMap[f]
else:
self._flags |= flagMap[f]
except KeyError:
raise error.PyAsn1Error('bad debug flag %s' % f)
self('debug category \'%s\' %s' % (f, inverse and 'disabled' or 'enabled'))
def __str__(self): def __str__(self):
return 'logger %s, flags %x' % (self._printer, self._flags) return 'logger %s, flags %x' % (self._printer, self._flags)
def __call__(self, msg): def __call__(self, msg):
self._printer('DBG: %s\n' % msg) self._printer(msg)
def __and__(self, flag): def __and__(self, flag):
return self._flags & flag return self._flags & flag

78
libs/pyasn1/type/base.py

@ -1,13 +1,13 @@
# Base classes for ASN.1 types # Base classes for ASN.1 types
import sys import sys
from pyasn1.type import constraint, tagmap from pyasn1.type import constraint, tagmap, tag
from pyasn1 import error from pyasn1 import error
class Asn1Item: pass class Asn1Item: pass
class Asn1ItemBase(Asn1Item): class Asn1ItemBase(Asn1Item):
# Set of tags for this ASN.1 type # Set of tags for this ASN.1 type
tagSet = () tagSet = tag.TagSet()
# A list of constraint.Constraint instances for checking values # A list of constraint.Constraint instances for checking values
subtypeSpec = constraint.ConstraintsIntersection() subtypeSpec = constraint.ConstraintsIntersection()
@ -38,22 +38,28 @@ class Asn1ItemBase(Asn1Item):
def getEffectiveTagSet(self): return self._tagSet # used by untagged types def getEffectiveTagSet(self): return self._tagSet # used by untagged types
def getTagMap(self): return tagmap.TagMap({self._tagSet: self}) def getTagMap(self): return tagmap.TagMap({self._tagSet: self})
def isSameTypeWith(self, other): def isSameTypeWith(self, other, matchTags=True, matchConstraints=True):
return self is other or \ return self is other or \
self._tagSet == other.getTagSet() and \ (not matchTags or \
self._subtypeSpec == other.getSubtypeSpec() self._tagSet == other.getTagSet()) and \
def isSuperTypeOf(self, other): (not matchConstraints or \
self._subtypeSpec==other.getSubtypeSpec())
def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
"""Returns true if argument is a ASN1 subtype of ourselves""" """Returns true if argument is a ASN1 subtype of ourselves"""
return self._tagSet.isSuperTagSetOf(other.getTagSet()) and \ return (not matchTags or \
self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec()) self._tagSet.isSuperTagSetOf(other.getTagSet())) and \
(not matchConstraints or \
(self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())))
class __NoValue: class NoValue:
def __getattr__(self, attr): def __getattr__(self, attr):
raise error.PyAsn1Error('No value for %s()' % attr) raise error.PyAsn1Error('No value for %s()' % attr)
def __getitem__(self, i): def __getitem__(self, i):
raise error.PyAsn1Error('No value') raise error.PyAsn1Error('No value')
def __repr__(self): return '%s()' % self.__class__.__name__
noValue = __NoValue() noValue = NoValue()
# Base class for "simple" ASN.1 objects. These are immutable. # Base class for "simple" ASN.1 objects. These are immutable.
class AbstractSimpleAsn1Item(Asn1ItemBase): class AbstractSimpleAsn1Item(Asn1ItemBase):
@ -72,10 +78,15 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
self._len = None self._len = None
def __repr__(self): def __repr__(self):
if self._value is noValue: r = []
return self.__class__.__name__ + '()' if self._value is not self.defaultValue:
else: r.append(self.prettyOut(self._value))
return self.__class__.__name__ + '(%s)' % (self.prettyOut(self._value),) if self._tagSet is not self.tagSet:
r.append('tagSet=%r' % (self._tagSet,))
if self._subtypeSpec is not self.subtypeSpec:
r.append('subtypeSpec=%r' % (self._subtypeSpec,))
return '%s(%s)' % (self.__class__.__name__, ', '.join(r))
def __str__(self): return str(self._value) def __str__(self): return str(self._value)
def __eq__(self, other): def __eq__(self, other):
return self is other and True or self._value == other return self is other and True or self._value == other
@ -90,6 +101,9 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
def __bool__(self): return bool(self._value) def __bool__(self): return bool(self._value)
def __hash__(self): return self.__hashedValue def __hash__(self): return self.__hashedValue
def hasValue(self):
return not isinstance(self._value, NoValue)
def clone(self, value=None, tagSet=None, subtypeSpec=None): def clone(self, value=None, tagSet=None, subtypeSpec=None):
if value is None and tagSet is None and subtypeSpec is None: if value is None and tagSet is None and subtypeSpec is None:
return self return self
@ -121,14 +135,17 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
def prettyOut(self, value): return str(value) def prettyOut(self, value): return str(value)
def prettyPrint(self, scope=0): def prettyPrint(self, scope=0):
if self._value is noValue: if self.hasValue():
return '<no value>'
else:
return self.prettyOut(self._value) return self.prettyOut(self._value)
else:
return '<no value>'
# XXX Compatibility stub # XXX Compatibility stub
def prettyPrinter(self, scope=0): return self.prettyPrint(scope) def prettyPrinter(self, scope=0): return self.prettyPrint(scope)
def prettyPrintType(self, scope=0):
return '%s -> %s' % (self.getTagSet(), self.__class__.__name__)
# #
# Constructed types: # Constructed types:
# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice # * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
@ -166,13 +183,16 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
self._componentValuesSet = 0 self._componentValuesSet = 0
def __repr__(self): def __repr__(self):
r = self.__class__.__name__ + '()' r = []
for idx in range(len(self._componentValues)): if self._componentType is not self.componentType:
if self._componentValues[idx] is None: r.append('componentType=%r' % (self._componentType,))
continue if self._tagSet is not self.tagSet:
r = r + '.setComponentByPosition(%s, %r)' % ( r.append('tagSet=%r' % (self._tagSet,))
idx, self._componentValues[idx] if self._subtypeSpec is not self.subtypeSpec:
) r.append('subtypeSpec=%r' % (self._subtypeSpec,))
r = '%s(%s)' % (self.__class__.__name__, ', '.join(r))
if self._componentValues:
r += '.setComponents(%s)' % ', '.join([repr(x) for x in self._componentValues])
return r return r
def __eq__(self, other): def __eq__(self, other):
@ -235,8 +255,17 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
def setComponentByPosition(self, idx, value, verifyConstraints=True): def setComponentByPosition(self, idx, value, verifyConstraints=True):
raise error.PyAsn1Error('Method not implemented') raise error.PyAsn1Error('Method not implemented')
def setComponents(self, *args, **kwargs):
for idx in range(len(args)):
self[idx] = args[idx]
for k in kwargs:
self[k] = kwargs[k]
return self
def getComponentType(self): return self._componentType def getComponentType(self): return self._componentType
def setDefaultComponents(self): pass
def __getitem__(self, idx): return self.getComponentByPosition(idx) def __getitem__(self, idx): return self.getComponentByPosition(idx)
def __setitem__(self, idx, value): self.setComponentByPosition(idx, value) def __setitem__(self, idx, value): self.setComponentByPosition(idx, value)
@ -246,4 +275,3 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
self._componentValues = [] self._componentValues = []
self._componentValuesSet = 0 self._componentValuesSet = 0
def setDefaultComponents(self): pass

17
libs/pyasn1/type/char.py

@ -1,12 +1,6 @@
# ASN.1 "character string" types # ASN.1 "character string" types
from pyasn1.type import univ, tag from pyasn1.type import univ, tag
class UTF8String(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
)
encoding = "utf-8"
class NumericString(univ.OctetString): class NumericString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly( tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18)
@ -21,7 +15,8 @@ class TeletexString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly( tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20)
) )
class T61String(TeletexString): pass
class VideotexString(univ.OctetString): class VideotexString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly( tagSet = univ.OctetString.tagSet.tagImplicitly(
@ -43,6 +38,8 @@ class VisibleString(univ.OctetString):
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26)
) )
class ISO646String(VisibleString): pass
class GeneralString(univ.OctetString): class GeneralString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly( tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27)
@ -59,3 +56,9 @@ class BMPString(univ.OctetString):
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30)
) )
encoding = "utf-16-be" encoding = "utf-16-be"
class UTF8String(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
)
encoding = "utf-8"

31
libs/pyasn1/type/namedtype.py

@ -8,9 +8,17 @@ class NamedType:
isDefaulted = 0 isDefaulted = 0
def __init__(self, name, t): def __init__(self, name, t):
self.__name = name; self.__type = t self.__name = name; self.__type = t
def __repr__(self): return '%s(%s, %s)' % ( def __repr__(self): return '%s(%r, %r)' % (
self.__class__.__name__, self.__name, self.__type self.__class__.__name__, self.__name, self.__type
) )
def __eq__(self, other): return tuple(self) == tuple(other)
def __ne__(self, other): return tuple(self) != tuple(other)
def __lt__(self, other): return tuple(self) < tuple(other)
def __le__(self, other): return tuple(self) <= tuple(other)
def __gt__(self, other): return tuple(self) > tuple(other)
def __ge__(self, other): return tuple(self) >= tuple(other)
def __hash__(self): return hash(tuple(self))
def getType(self): return self.__type def getType(self): return self.__type
def getName(self): return self.__name def getName(self): return self.__name
def __getitem__(self, idx): def __getitem__(self, idx):
@ -33,11 +41,18 @@ class NamedTypes:
self.__ambigiousTypes = {} self.__ambigiousTypes = {}
def __repr__(self): def __repr__(self):
r = '%s(' % self.__class__.__name__ return '%s(%s)' % (
for n in self.__namedTypes: self.__class__.__name__,
r = r + '%r, ' % (n,) ', '.join([ repr(x) for x in self.__namedTypes ])
return r + ')' )
def __eq__(self, other): return tuple(self) == tuple(other)
def __ne__(self, other): return tuple(self) != tuple(other)
def __lt__(self, other): return tuple(self) < tuple(other)
def __le__(self, other): return tuple(self) <= tuple(other)
def __gt__(self, other): return tuple(self) > tuple(other)
def __ge__(self, other): return tuple(self) >= tuple(other)
def __hash__(self): return hash(tuple(self))
def __getitem__(self, idx): return self.__namedTypes[idx] def __getitem__(self, idx): return self.__namedTypes[idx]
if sys.version_info[0] <= 2: if sys.version_info[0] <= 2:
@ -45,7 +60,9 @@ class NamedTypes:
else: else:
def __bool__(self): return bool(self.__namedTypesLen) def __bool__(self): return bool(self.__namedTypesLen)
def __len__(self): return self.__namedTypesLen def __len__(self): return self.__namedTypesLen
def clone(self): return self.__class__(*self.__namedTypes)
def getTypeByPosition(self, idx): def getTypeByPosition(self, idx):
if idx < 0 or idx >= self.__namedTypesLen: if idx < 0 or idx >= self.__namedTypesLen:
raise error.PyAsn1Error('Type position out of range') raise error.PyAsn1Error('Type position out of range')

12
libs/pyasn1/type/namedval.py

@ -22,7 +22,19 @@ class NamedValues:
self.valToNameIdx[val] = name self.valToNameIdx[val] = name
self.namedValues = self.namedValues + ((name, val),) self.namedValues = self.namedValues + ((name, val),)
automaticVal = automaticVal + 1 automaticVal = automaticVal + 1
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(x) for x in self.namedValues]))
def __str__(self): return str(self.namedValues) def __str__(self): return str(self.namedValues)
def __eq__(self, other): return tuple(self) == tuple(other)
def __ne__(self, other): return tuple(self) != tuple(other)
def __lt__(self, other): return tuple(self) < tuple(other)
def __le__(self, other): return tuple(self) <= tuple(other)
def __gt__(self, other): return tuple(self) > tuple(other)
def __ge__(self, other): return tuple(self) >= tuple(other)
def __hash__(self): return hash(tuple(self))
def getName(self, value): def getName(self, value):
if value in self.valToNameIdx: if value in self.valToNameIdx:

10
libs/pyasn1/type/tag.py

@ -24,6 +24,9 @@ class Tag:
self.uniq = (tagClass, tagId) self.uniq = (tagClass, tagId)
self.__hashedUniqTag = hash(self.uniq) self.__hashedUniqTag = hash(self.uniq)
def __str__(self):
return '[%s:%s:%s]' % self.__tag
def __repr__(self): def __repr__(self):
return '%s(tagClass=%s, tagFormat=%s, tagId=%s)' % ( return '%s(tagClass=%s, tagFormat=%s, tagId=%s)' % (
(self.__class__.__name__,) + self.__tag (self.__class__.__name__,) + self.__tag
@ -62,11 +65,14 @@ class TagSet:
_uniq = _uniq + t.uniq _uniq = _uniq + t.uniq
self.uniq = _uniq self.uniq = _uniq
self.__lenOfSuperTags = len(superTags) self.__lenOfSuperTags = len(superTags)
def __str__(self):
return self.__superTags and '+'.join([str(x) for x in self.__superTags]) or '[untagged]'
def __repr__(self): def __repr__(self):
return '%s(%s)' % ( return '%s(%s)' % (
self.__class__.__name__, self.__class__.__name__,
', '.join([repr(x) for x in self.__superTags]) '(), ' + ', '.join([repr(x) for x in self.__superTags])
) )
def __add__(self, superTag): def __add__(self, superTag):

18
libs/pyasn1/type/tagmap.py

@ -21,9 +21,23 @@ class TagMap:
raise KeyError() raise KeyError()
def __repr__(self): def __repr__(self):
s = '%r/%r' % (self.__posMap, self.__negMap) s = self.__class__.__name__ + '('
if self.__posMap:
s = s + 'posMap=%r, ' % (self.__posMap,)
if self.__negMap:
s = s + 'negMap=%r, ' % (self.__negMap,)
if self.__defType is not None: if self.__defType is not None:
s = s + '/%r' % (self.__defType,) s = s + 'defType=%r' % (self.__defType,)
return s + ')'
def __str__(self):
s = self.__class__.__name__ + ':\n'
if self.__posMap:
s = s + 'posMap:\n%s, ' % ',\n '.join([ x.prettyPrintType() for x in self.__posMap.values()])
if self.__negMap:
s = s + 'negMap:\n%s, ' % ',\n '.join([ x.prettyPrintType() for x in self.__negMap.values()])
if self.__defType is not None:
s = s + 'defType:\n%s, ' % self.__defType.prettyPrintType()
return s return s
def clone(self, parentType, tagMap, uniq=False): def clone(self, parentType, tagMap, uniq=False):

230
libs/pyasn1/type/univ.py

@ -1,5 +1,5 @@
# ASN.1 "universal" data types # ASN.1 "universal" data types
import operator, sys import operator, sys, math
from pyasn1.type import base, tag, constraint, namedtype, namedval, tagmap from pyasn1.type import base, tag, constraint, namedtype, namedval, tagmap
from pyasn1.codec.ber import eoo from pyasn1.codec.ber import eoo
from pyasn1.compat import octets from pyasn1.compat import octets
@ -22,6 +22,12 @@ class Integer(base.AbstractSimpleAsn1Item):
self, value, tagSet, subtypeSpec self, value, tagSet, subtypeSpec
) )
def __repr__(self):
if self.__namedValues is not self.namedValues:
return '%s, %r)' % (base.AbstractSimpleAsn1Item.__repr__(self)[:-1], self.__namedValues)
else:
return base.AbstractSimpleAsn1Item.__repr__(self)
def __and__(self, value): return self.clone(self._value & value) def __and__(self, value): return self.clone(self._value & value)
def __rand__(self, value): return self.clone(value & self._value) def __rand__(self, value): return self.clone(value & self._value)
def __or__(self, value): return self.clone(self._value | value) def __or__(self, value): return self.clone(self._value | value)
@ -57,8 +63,21 @@ class Integer(base.AbstractSimpleAsn1Item):
if sys.version_info[0] <= 2: if sys.version_info[0] <= 2:
def __long__(self): return long(self._value) def __long__(self): return long(self._value)
def __float__(self): return float(self._value) def __float__(self): return float(self._value)
def __abs__(self): return abs(self._value) def __abs__(self): return self.clone(abs(self._value))
def __index__(self): return int(self._value) def __index__(self): return int(self._value)
def __pos__(self): return self.clone(+self._value)
def __neg__(self): return self.clone(-self._value)
def __invert__(self): return self.clone(~self._value)
def __round__(self, n=0):
r = round(self._value, n)
if n:
return self.clone(r)
else:
return r
def __floor__(self): return math.floor(self._value)
def __ceil__(self): return math.ceil(self._value)
if sys.version_info[0:2] > (2, 5):
def __trunc__(self): return self.clone(math.trunc(self._value))
def __lt__(self, value): return self._value < value def __lt__(self, value): return self._value < value
def __le__(self, value): return self._value <= value def __le__(self, value): return self._value <= value
@ -73,7 +92,7 @@ class Integer(base.AbstractSimpleAsn1Item):
return int(value) return int(value)
except: except:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Can\'t coerce %s into integer: %s' % (value, sys.exc_info()[1]) 'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
) )
r = self.__namedValues.getValue(value) r = self.__namedValues.getValue(value)
if r is not None: if r is not None:
@ -82,7 +101,7 @@ class Integer(base.AbstractSimpleAsn1Item):
return int(value) return int(value)
except: except:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Can\'t coerce %s into integer: %s' % (value, sys.exc_info()[1]) 'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
) )
def prettyOut(self, value): def prettyOut(self, value):
@ -260,6 +279,15 @@ class BitString(base.AbstractSimpleAsn1Item):
def prettyOut(self, value): def prettyOut(self, value):
return '\"\'%s\'B\"' % ''.join([str(x) for x in value]) return '\"\'%s\'B\"' % ''.join([str(x) for x in value])
try:
all
except NameError: # Python 2.4
def all(iterable):
for element in iterable:
if not element:
return False
return True
class OctetString(base.AbstractSimpleAsn1Item): class OctetString(base.AbstractSimpleAsn1Item):
tagSet = baseTagSet = tag.initTagSet( tagSet = baseTagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
@ -280,7 +308,7 @@ class OctetString(base.AbstractSimpleAsn1Item):
value = self.defaultHexValue value = self.defaultHexValue
if value is None or value is base.noValue: if value is None or value is base.noValue:
value = self.defaultBinValue value = self.defaultBinValue
self.__intValue = None self.__asNumbersCache = None
base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec) base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec)
def clone(self, value=None, tagSet=None, subtypeSpec=None, def clone(self, value=None, tagSet=None, subtypeSpec=None,
@ -304,19 +332,33 @@ class OctetString(base.AbstractSimpleAsn1Item):
def prettyIn(self, value): def prettyIn(self, value):
if isinstance(value, str): if isinstance(value, str):
return value return value
elif isinstance(value, unicode):
try:
return value.encode(self._encoding)
except (LookupError, UnicodeEncodeError):
raise error.PyAsn1Error(
'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
)
elif isinstance(value, (tuple, list)): elif isinstance(value, (tuple, list)):
try: try:
return ''.join([ chr(x) for x in value ]) return ''.join([ chr(x) for x in value ])
except ValueError: except ValueError:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Bad OctetString initializer \'%s\'' % (value,) 'Bad OctetString initializer \'%s\'' % (value,)
) )
else: else:
return str(value) return str(value)
else: else:
def prettyIn(self, value): def prettyIn(self, value):
if isinstance(value, bytes): if isinstance(value, bytes):
return value return value
elif isinstance(value, str):
try:
return value.encode(self._encoding)
except UnicodeEncodeError:
raise error.PyAsn1Error(
'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
)
elif isinstance(value, OctetString): elif isinstance(value, OctetString):
return value.asOctets() return value.asOctets()
elif isinstance(value, (tuple, list, map)): elif isinstance(value, (tuple, list, map)):
@ -325,14 +367,14 @@ class OctetString(base.AbstractSimpleAsn1Item):
except ValueError: except ValueError:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Bad OctetString initializer \'%s\'' % (value,) 'Bad OctetString initializer \'%s\'' % (value,)
) )
else: else:
try: try:
return str(value).encode(self._encoding) return str(value).encode(self._encoding)
except UnicodeEncodeError: except UnicodeEncodeError:
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding) 'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
) )
def fromBinaryString(self, value): def fromBinaryString(self, value):
@ -369,21 +411,33 @@ class OctetString(base.AbstractSimpleAsn1Item):
def prettyOut(self, value): def prettyOut(self, value):
if sys.version_info[0] <= 2: if sys.version_info[0] <= 2:
numbers = tuple([ ord(x) for x in value ]) numbers = tuple(( ord(x) for x in value ))
else: else:
numbers = tuple(value) numbers = tuple(value)
if [ x for x in numbers if x < 32 or x > 126 ]: if all(x >= 32 and x <= 126 for x in numbers):
return '0x' + ''.join([ '%.2x' % x for x in numbers ])
else:
return str(value) return str(value)
else:
return '0x' + ''.join(( '%.2x' % x for x in numbers ))
def __repr__(self): def __repr__(self):
if self._value is base.noValue: r = []
return self.__class__.__name__ + '()' doHex = False
if [ x for x in self.asNumbers() if x < 32 or x > 126 ]: if self._value is not self.defaultValue:
return self.__class__.__name__ + '(hexValue=\'' + ''.join([ '%.2x' % x for x in self.asNumbers() ])+'\')' for x in self.asNumbers():
else: if x < 32 or x > 126:
return self.__class__.__name__ + '(\'' + self.prettyOut(self._value) + '\')' doHex = True
break
if not doHex:
r.append('%r' % (self._value,))
if self._tagSet is not self.tagSet:
r.append('tagSet=%r' % (self._tagSet,))
if self._subtypeSpec is not self.subtypeSpec:
r.append('subtypeSpec=%r' % (self._subtypeSpec,))
if self.encoding is not self._encoding:
r.append('encoding=%r' % (self._encoding,))
if doHex:
r.append('hexValue=%r' % ''.join([ '%.2x' % x for x in self.asNumbers() ]))
return '%s(%s)' % (self.__class__.__name__, ', '.join(r))
if sys.version_info[0] <= 2: if sys.version_info[0] <= 2:
def __str__(self): return str(self._value) def __str__(self): return str(self._value)
@ -391,17 +445,17 @@ class OctetString(base.AbstractSimpleAsn1Item):
return self._value.decode(self._encoding, 'ignore') return self._value.decode(self._encoding, 'ignore')
def asOctets(self): return self._value def asOctets(self): return self._value
def asNumbers(self): def asNumbers(self):
if self.__intValue is None: if self.__asNumbersCache is None:
self.__intValue = tuple([ ord(x) for x in self._value ]) self.__asNumbersCache = tuple([ ord(x) for x in self._value ])
return self.__intValue return self.__asNumbersCache
else: else:
def __str__(self): return self._value.decode(self._encoding, 'ignore') def __str__(self): return self._value.decode(self._encoding, 'ignore')
def __bytes__(self): return self._value def __bytes__(self): return self._value
def asOctets(self): return self._value def asOctets(self): return self._value
def asNumbers(self): def asNumbers(self):
if self.__intValue is None: if self.__asNumbersCache is None:
self.__intValue = tuple(self._value) self.__asNumbersCache = tuple(self._value)
return self.__intValue return self.__asNumbersCache
# Immutable sequence object protocol # Immutable sequence object protocol
@ -419,7 +473,9 @@ class OctetString(base.AbstractSimpleAsn1Item):
def __radd__(self, value): return self.clone(self.prettyIn(value) + self._value) def __radd__(self, value): return self.clone(self.prettyIn(value) + self._value)
def __mul__(self, value): return self.clone(self._value * value) def __mul__(self, value): return self.clone(self._value * value)
def __rmul__(self, value): return self * value def __rmul__(self, value): return self * value
def __int__(self): return int(self._value)
def __float__(self): return float(self._value)
class Null(OctetString): class Null(OctetString):
defaultValue = ''.encode() # This is tightly constrained defaultValue = ''.encode() # This is tightly constrained
tagSet = baseTagSet = tag.initTagSet( tagSet = baseTagSet = tag.initTagSet(
@ -430,7 +486,9 @@ class Null(OctetString):
if sys.version_info[0] <= 2: if sys.version_info[0] <= 2:
intTypes = (int, long) intTypes = (int, long)
else: else:
intTypes = int intTypes = (int,)
numericTypes = intTypes + (float,)
class ObjectIdentifier(base.AbstractSimpleAsn1Item): class ObjectIdentifier(base.AbstractSimpleAsn1Item):
tagSet = baseTagSet = tag.initTagSet( tagSet = baseTagSet = tag.initTagSet(
@ -456,7 +514,9 @@ class ObjectIdentifier(base.AbstractSimpleAsn1Item):
return self._value[i] return self._value[i]
def __str__(self): return self.prettyPrint() def __str__(self): return self.prettyPrint()
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.prettyPrint())
def index(self, suboid): return self._value.index(suboid) def index(self, suboid): return self._value.index(suboid)
def isPrefixOf(self, value): def isPrefixOf(self, value):
@ -504,6 +564,7 @@ class ObjectIdentifier(base.AbstractSimpleAsn1Item):
def prettyOut(self, value): return '.'.join([ str(x) for x in value ]) def prettyOut(self, value): return '.'.join([ str(x) for x in value ])
class Real(base.AbstractSimpleAsn1Item): class Real(base.AbstractSimpleAsn1Item):
binEncBase = None # binEncBase = 16 is recommended for large numbers
try: try:
_plusInf = float('inf') _plusInf = float('inf')
_minusInf = float('-inf') _minusInf = float('-inf')
@ -526,11 +587,13 @@ class Real(base.AbstractSimpleAsn1Item):
def prettyIn(self, value): def prettyIn(self, value):
if isinstance(value, tuple) and len(value) == 3: if isinstance(value, tuple) and len(value) == 3:
for d in value: if not isinstance(value[0], numericTypes) or \
if not isinstance(d, intTypes): not isinstance(value[1], intTypes) or \
raise error.PyAsn1Error( not isinstance(value[2], intTypes):
'Lame Real value syntax: %s' % (value,) raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
) if isinstance(value[0], float) and \
self._inf and value[0] in self._inf:
return value[0]
if value[1] not in (2, 10): if value[1] not in (2, 10):
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Prohibited base for Real value: %s' % (value[1],) 'Prohibited base for Real value: %s' % (value[1],)
@ -540,7 +603,14 @@ class Real(base.AbstractSimpleAsn1Item):
return value return value
elif isinstance(value, intTypes): elif isinstance(value, intTypes):
return self.__normalizeBase10((value, 10, 0)) return self.__normalizeBase10((value, 10, 0))
elif isinstance(value, float): elif isinstance(value, (str, float)):
if isinstance(value, str):
try:
value = float(value)
except ValueError:
raise error.PyAsn1Error(
'Bad real value syntax: %s' % (value,)
)
if self._inf and value in self._inf: if self._inf and value in self._inf:
return value return value
else: else:
@ -551,11 +621,6 @@ class Real(base.AbstractSimpleAsn1Item):
return self.__normalizeBase10((int(value), 10, e)) return self.__normalizeBase10((int(value), 10, e))
elif isinstance(value, Real): elif isinstance(value, Real):
return tuple(value) return tuple(value)
elif isinstance(value, str): # handle infinite literal
try:
return float(value)
except ValueError:
pass
raise error.PyAsn1Error( raise error.PyAsn1Error(
'Bad real value syntax: %s' % (value,) 'Bad real value syntax: %s' % (value,)
) )
@ -566,6 +631,12 @@ class Real(base.AbstractSimpleAsn1Item):
else: else:
return str(value) return str(value)
def prettyPrint(self, scope=0):
if self.isInfinity():
return self.prettyOut(self._value)
else:
return str(float(self))
def isPlusInfinity(self): return self._value == self._plusInf def isPlusInfinity(self): return self._value == self._plusInf
def isMinusInfinity(self): return self._value == self._minusInf def isMinusInfinity(self): return self._value == self._minusInf
def isInfinity(self): return self._value in self._inf def isInfinity(self): return self._value in self._inf
@ -601,8 +672,20 @@ class Real(base.AbstractSimpleAsn1Item):
else: else:
return float( return float(
self._value[0] * pow(self._value[1], self._value[2]) self._value[0] * pow(self._value[1], self._value[2])
) )
def __abs__(self): return abs(float(self)) def __abs__(self): return self.clone(abs(float(self)))
def __pos__(self): return self.clone(+float(self))
def __neg__(self): return self.clone(-float(self))
def __round__(self, n=0):
r = round(float(self), n)
if n:
return self.clone(r)
else:
return r
def __floor__(self): return self.clone(math.floor(float(self)))
def __ceil__(self): return self.clone(math.ceil(float(self)))
if sys.version_info[0:2] > (2, 5):
def __trunc__(self): return self.clone(math.trunc(float(self)))
def __lt__(self, value): return float(self) < value def __lt__(self, value): return float(self) < value
def __le__(self, value): return float(self) <= value def __le__(self, value): return float(self) <= value
@ -636,6 +719,7 @@ class SetOf(base.AbstractConstructedAsn1Item):
tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
) )
typeId = 1 typeId = 1
strictConstraints = False
def _cloneComponentValues(self, myClone, cloneValueFlag): def _cloneComponentValues(self, myClone, cloneValueFlag):
idx = 0; l = len(self._componentValues) idx = 0; l = len(self._componentValues)
@ -651,9 +735,14 @@ class SetOf(base.AbstractConstructedAsn1Item):
idx = idx + 1 idx = idx + 1
def _verifyComponent(self, idx, value): def _verifyComponent(self, idx, value):
if self._componentType is not None and \ t = self._componentType
not self._componentType.isSuperTypeOf(value): if t is None:
raise error.PyAsn1Error('Component type error %s' % (value,)) return
if not t.isSameTypeWith(value,matchConstraints=self.strictConstraints):
raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
if self.strictConstraints and \
not t.isSuperTypeOf(value, matchTags=False):
raise error.PyAsn1Error('Component value is constraints-incompatible: %r vs %r' % (value, t))
def getComponentByPosition(self, idx): return self._componentValues[idx] def getComponentByPosition(self, idx): return self._componentValues[idx]
def setComponentByPosition(self, idx, value=None, verifyConstraints=True): def setComponentByPosition(self, idx, value=None, verifyConstraints=True):
@ -698,6 +787,14 @@ class SetOf(base.AbstractConstructedAsn1Item):
r = r + self._componentValues[idx].prettyPrint(scope) r = r + self._componentValues[idx].prettyPrint(scope)
return r return r
def prettyPrintType(self, scope=0):
scope = scope + 1
r = '%s -> %s {\n' % (self.getTagSet(), self.__class__.__name__)
if self._componentType is not None:
r = r + ' '*scope
r = r + self._componentType.prettyPrintType(scope)
return r + '\n' + ' '*(scope-1) + '}'
class SequenceOf(SetOf): class SequenceOf(SetOf):
tagSet = baseTagSet = tag.initTagSet( tagSet = baseTagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
@ -706,15 +803,15 @@ class SequenceOf(SetOf):
class SequenceAndSetBase(base.AbstractConstructedAsn1Item): class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
componentType = namedtype.NamedTypes() componentType = namedtype.NamedTypes()
strictConstraints = False
def __init__(self, componentType=None, tagSet=None, def __init__(self, componentType=None, tagSet=None,
subtypeSpec=None, sizeSpec=None): subtypeSpec=None, sizeSpec=None):
if componentType is None:
componentType = self.componentType
base.AbstractConstructedAsn1Item.__init__( base.AbstractConstructedAsn1Item.__init__(
self, componentType, tagSet, subtypeSpec, sizeSpec self, componentType.clone(), tagSet, subtypeSpec, sizeSpec
) )
if self._componentType is None: self._componentTypeLen = len(self._componentType)
self._componentTypeLen = 0
else:
self._componentTypeLen = len(self._componentType)
def __getitem__(self, idx): def __getitem__(self, idx):
if isinstance(idx, str): if isinstance(idx, str):
@ -747,8 +844,11 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
'Component type error out of range' 'Component type error out of range'
) )
t = self._componentType[idx].getType() t = self._componentType[idx].getType()
if not t.isSuperTypeOf(value): if not t.isSameTypeWith(value,matchConstraints=self.strictConstraints):
raise error.PyAsn1Error('Component type error %r vs %r' % (t, value)) raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
if self.strictConstraints and \
not t.isSuperTypeOf(value, matchTags=False):
raise error.PyAsn1Error('Component value is constraints-incompatible: %r vs %r' % (value, t))
def getComponentByName(self, name): def getComponentByName(self, name):
return self.getComponentByPosition( return self.getComponentByPosition(
@ -756,9 +856,8 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
) )
def setComponentByName(self, name, value=None, verifyConstraints=True): def setComponentByName(self, name, value=None, verifyConstraints=True):
return self.setComponentByPosition( return self.setComponentByPosition(
self._componentType.getPositionByName(name), value, self._componentType.getPositionByName(name),value,verifyConstraints
verifyConstraints )
)
def getComponentByPosition(self, idx): def getComponentByPosition(self, idx):
try: try:
@ -767,7 +866,11 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
if idx < self._componentTypeLen: if idx < self._componentTypeLen:
return return
raise raise
def setComponentByPosition(self, idx, value=None, verifyConstraints=True): def setComponentByPosition(self, idx, value=None,
verifyConstraints=True,
exactTypes=False,
matchTags=True,
matchConstraints=True):
l = len(self._componentValues) l = len(self._componentValues)
if idx >= l: if idx >= l:
self._componentValues = self._componentValues + (idx-l+1)*[None] self._componentValues = self._componentValues + (idx-l+1)*[None]
@ -834,6 +937,17 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
) )
return r return r
def prettyPrintType(self, scope=0):
scope = scope + 1
r = '%s -> %s {\n' % (self.getTagSet(), self.__class__.__name__)
for idx in range(len(self.componentType)):
r = r + ' '*scope
r = r + '"%s"' % self.componentType.getNameByPosition(idx)
r = '%s = %s\n' % (
r, self._componentType.getTypeByPosition(idx).prettyPrintType(scope)
)
return r + '\n' + ' '*(scope-1) + '}'
class Sequence(SequenceAndSetBase): class Sequence(SequenceAndSetBase):
tagSet = baseTagSet = tag.initTagSet( tagSet = baseTagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
@ -877,16 +991,16 @@ class Set(SequenceAndSetBase):
if t.getTagSet(): if t.getTagSet():
return self.setComponentByPosition( return self.setComponentByPosition(
idx, value, verifyConstraints idx, value, verifyConstraints
) )
else: else:
t = self.setComponentByPosition(idx).getComponentByPosition(idx) t = self.setComponentByPosition(idx).getComponentByPosition(idx)
return t.setComponentByType( return t.setComponentByType(
tagSet, value, innerFlag, verifyConstraints tagSet, value, innerFlag, verifyConstraints
) )
else: # set outer component by inner tagSet else: # set outer component by inner tagSet
return self.setComponentByPosition( return self.setComponentByPosition(
idx, value, verifyConstraints idx, value, verifyConstraints
) )
def getComponentTagMap(self): def getComponentTagMap(self):
if self._componentType: if self._componentType:

5
libs/pyasn1/type/useful.py

@ -1,6 +1,11 @@
# ASN.1 "useful" types # ASN.1 "useful" types
from pyasn1.type import char, tag from pyasn1.type import char, tag
class ObjectDescriptor(char.GraphicString):
tagSet = char.GraphicString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7)
)
class GeneralizedTime(char.VisibleString): class GeneralizedTime(char.VisibleString):
tagSet = char.VisibleString.tagSet.tagImplicitly( tagSet = char.VisibleString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24) tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24)

Loading…
Cancel
Save