def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check? if not head: raise error.PyAsn1Error('Empty substrate') trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error('Trailing bits overflow %s' % trailingBits) head = head[1:] lsb = p = 0 l = len(head) - 1 b = [] while p <= l: if p == l: lsb = trailingBits j = 7 o = oct2int(head[p]) while j >= lsb: b.append((o >> j) & 0x01) j -= 1 p += 1 return self._createComponent(asn1Spec, tagSet, b), tail r = self._createComponent(asn1Spec, tagSet, ()) if substrateFun: return substrateFun(r, substrate, length) while head: component, head = decodeFun(head, self.protoComponent) r = r + component return r, tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): substrate = substrate[:length] if not substrate: raise error.PyAsn1Error('Empty substrate') oid = (); index = 0 # Get the first subid subId = oct2int(substrate[index]) oid = oid + divmod(subId, 40) index = index + 1 substrateLen = len(substrate) while index < substrateLen: subId = oct2int(substrate[index]) if subId < 128: oid = oid + (subId,) index = index + 1 else: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128 and index < substrateLen: subId = (subId << 7) + (nextSubId & 0x7F) index = index + 1 nextSubId = oct2int(substrate[index]) if index == substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for OID %s' % oid ) subId = (subId << 7) + nextSubId oid = oid + (subId,) index = index + 1 return self._createComponent(asn1Spec, tagSet, oid), substrate[index:]
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check? if not head: raise error.PyAsn1Error('Empty substrate') trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) head = head[1:] lsb = p = 0; l = len(head)-1; b = [] while p <= l: if p == l: lsb = trailingBits j = 7 o = oct2int(head[p]) while j >= lsb: b.append((o>>j)&0x01) j -= 1 p += 1 return self._createComponent(asn1Spec, tagSet, b), tail r = self._createComponent(asn1Spec, tagSet, ()) if substrateFun: return substrateFun(r, substrate, length) while head: component, head = decodeFun(head, self.protoComponent) r = r + component return r, tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0.0), tail fo = oct2int(head[0]) head = head[1:] if fo & 0x80: # binary encoding if not head: raise error.PyAsn1Error("Incomplete floating-point value") n = (fo & 0x03) + 1 if n == 4: n = oct2int(head[0]) head = head[1:] eo, head = head[:n], head[n:] if not eo or not head: raise error.PyAsn1Error('Real exponent screwed') e = oct2int(eo[0]) & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= oct2int(eo[0]) 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 while head: # value p <<= 8 p |= oct2int(head[0]) head = head[1:] if fo & 0x40: # sign bit p = -p sf = fo >> 2 & 0x03 # scale bits p *= 2**sf value = (p, 2, e) elif fo & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' elif fo & 0xc0 == 0: # character encoding if not head: raise error.PyAsn1Error("Incomplete floating-point value") try: if fo & 0x3 == 0x1: # NR1 value = (int(head), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(head) elif fo & 0x3 == 0x3: # NR3 value = float(head) else: raise error.SubstrateUnderrunError('Unknown NR (tag %s)' % fo) except ValueError: raise error.SubstrateUnderrunError('Bad character Real syntax') else: raise error.SubstrateUnderrunError('Unknown encoding (tag %s)' % fo) return self._createComponent(asn1Spec, tagSet, value), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): substrate = substrate[:length] if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check? if not substrate: raise error.PyAsn1Error('Missing initial octet') trailingBits = oct2int(substrate[0]) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) substrate = substrate[1:] lsb = p = 0; l = len(substrate)-1; b = () while p <= l: if p == l: lsb = trailingBits j = 7 o = oct2int(substrate[p]) while j >= lsb: b = b + ((o>>j)&0x01,) j = j - 1 p = p + 1 return self._createComponent(asn1Spec, tagSet, b), '' r = self._createComponent(asn1Spec, tagSet, ()) if not decodeFun: return r, substrate while substrate: component, substrate = decodeFun(substrate) r = r + component return r, substrate
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') # Get the first subid subId = oct2int(head[0]) oid = divmod(subId, 40) index = 1 substrateLen = len(head) while index < substrateLen: subId = oct2int(head[index]) index = index + 1 if subId == 128: # ASN.1 spec forbids leading zeros (0x80) in sub-ID OID # 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: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128: subId = (subId << 7) + (nextSubId & 0x7F) if index >= substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for sub-OID past %s' % (oid,) ) nextSubId = oct2int(head[index]) index = index + 1 subId = (subId << 7) + nextSubId oid = oid + (subId,) return self._createComponent(asn1Spec, tagSet, oid), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0.0), tail fo = oct2int(head[0]); head = head[1:] if fo & 0x80: # binary enoding n = (fo & 0x03) + 1 if n == 4: n = oct2int(head[0]) head = head[1:] eo, head = head[:n], head[n:] if not eo or not head: raise error.PyAsn1Error('Real exponent screwed') e = oct2int(eo[0]) & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= oct2int(eo[0]) 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 while head: # value p <<= 8 p |= oct2int(head[0]) head = head[1:] if fo & 0x40: # sign bit p = -p sf = fo >> 2 & 0x03 # scale bits p *= 2**sf value = (p, 2, e) elif fo & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' elif fo & 0xc0 == 0: # character encoding try: if fo & 0x3 == 0x1: # NR1 value = (int(head), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = Decimal(head) elif fo & 0x3 == 0x3: # NR3 value = Decimal(head) else: raise error.SubstrateUnderrunError( 'Unknown NR (tag %s)' % fo ) except ValueError: raise error.SubstrateUnderrunError( 'Bad character Real syntax' ) else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) return self._createComponent(asn1Spec, tagSet, value), tail
def __asSocketAddress(self): if not hasattr(self, '__tuple_value'): v = self.asOctets() self.__tuple_value = ( inet_ntop(socket.AF_INET, v[:4]), oct2int(v[4]) << 8 | oct2int(v[5]), ) return self.__tuple_value
def __asSocketAddress(self): if not hasattr(self, '__tuple_value'): v = self.asOctets() self.__tuple_value = ( inet_ntop(AF_INET, v[:4]), oct2int(v[4]) << 8 | oct2int(v[5]) ) return self.__tuple_value
def __getitem__(self, i): if not hasattr(self, '__tuple_value'): v = self.asOctets() self.__tuple_value = ( inet_ntop(AF_INET, v[:4]), oct2int(v[4]) << 8 | oct2int(v[5]) ) return self.__tuple_value[i]
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): substrate = substrate[:length] if not length: raise error.SubstrateUnderrunError('Short substrate for Real') fo = oct2int(substrate[0]); substrate = substrate[1:] if fo & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' elif fo & 0x80: # binary enoding if fo & 0x11 == 0: n = 1 elif fo & 0x01: n = 2 elif fo & 0x02: n = 3 else: n = oct2int(substrate[0]) eo, substrate = substrate[:n], substrate[n:] if not eo or not substrate: raise error.PyAsn1Error('Real exponent screwed') e = 0 while eo: # exponent e <<= 8 e |= oct2int(eo[0]) eo = eo[1:] p = 0 while substrate: # value p <<= 8 p |= oct2int(substrate[0]) substrate = substrate[1:] if fo & 0x40: # sign bit p = -p value = (p, 2, e) elif fo & 0xc0 == 0: # character encoding try: if fo & 0x3 == 0x1: # NR1 value = (int(substrate), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(substrate) elif fo & 0x3 == 0x3: # NR3 value = float(substrate) else: raise error.SubstrateUnderrunError( 'Unknown NR (tag %s)' % fo ) except ValueError: raise error.SubstrateUnderrunError( 'Bad character Real syntax' ) elif fo & 0xc0 == 0x40: # special real value pass else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) return self._createComponent(asn1Spec, tagSet, value), substrate
def __getitem__(self, i): if not hasattr(self, '__tuple_value'): if not has_ipv6: raise error.PySnmpError('IPv6 not supported by platform') v = self.asOctets() self.__tuple_value = ( inet_ntop(socket.AF_INET6, v[:16]), oct2int(v[16]) << 8 | oct2int(v[17]), 0, # flowinfo 0) # scopeid return self.__tuple_value[i]
def __getitem__(self, i): if not hasattr(self, '__tuple_value'): if AF_INET6 is None: raise error.PySnmpError('IPv6 not supported by platform') v = self.asOctets() self.__tuple_value = ( inet_ntop(AF_INET6, v[:16]), oct2int(v[16]) << 8 | oct2int(v[17]), 0, 0) return self.__tuple_value[i]
def __asSocketAddress(self): if not hasattr(self, '__tuple_value'): if not has_ipv6: raise error.PySnmpError('IPv6 not supported by platform') v = self.asOctets() self.__tuple_value = ( inet_ntop(socket.AF_INET6, v[:16]), oct2int(v[16]) << 8 | oct2int(v[17]), 0, # flowinfo 0) # scopeid return self.__tuple_value
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.SubstrateUnderrunError('Short substrate for Real') fo = oct2int(head[0]); head = head[1:] if fo & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' elif fo & 0x80: # binary enoding n = (fo & 0x03) + 1 if n == 4: n = oct2int(head[0]) eo, head = head[:n], head[n:] if not eo or not head: raise error.PyAsn1Error('Real exponent screwed') e = oct2int(eo[0]) & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= oct2int(eo[0]) eo = eo[1:] p = 0 while head: # value p <<= 8 p |= oct2int(head[0]) head = head[1:] if fo & 0x40: # sign bit p = -p value = (p, 2, e) elif fo & 0xc0 == 0: # character encoding try: if fo & 0x3 == 0x1: # NR1 value = (int(head), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(head) elif fo & 0x3 == 0x3: # NR3 value = float(head) else: raise error.SubstrateUnderrunError( 'Unknown NR (tag %s)' % fo ) except ValueError: raise error.SubstrateUnderrunError( 'Bad character Real syntax' ) elif fo & 0xc0 == 0x40: # special real value pass else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) return self._createComponent(asn1Spec, tagSet, value), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0.0), tail fo = oct2int(head[0]); head = head[1:] if fo & 0x80: # binary enoding n = (fo & 0x03) + 1 if n == 4: n = oct2int(head[0]) eo, head = head[:n], head[n:] if not eo or not head: raise error.PyAsn1Error('Real exponent screwed') e = oct2int(eo[0]) & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= oct2int(eo[0]) eo = eo[1:] p = 0 while head: # value p <<= 8 p |= oct2int(head[0]) head = head[1:] if fo & 0x40: # sign bit p = -p value = (p, 2, e) elif fo & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' elif fo & 0xc0 == 0: # character encoding try: if fo & 0x3 == 0x1: # NR1 value = (int(head), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(head) elif fo & 0x3 == 0x3: # NR3 value = float(head) else: raise error.SubstrateUnderrunError( 'Unknown NR (tag %s)' % fo ) except ValueError: raise error.SubstrateUnderrunError( 'Bad character Real syntax' ) else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) return self._createComponent(asn1Spec, tagSet, value), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check? if not head: raise error.PyAsn1Error('Empty substrate') trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error('Trailing bits overflow %s' % trailingBits) head = head[1:] value = self.protoComponent.fromOctetString(head, trailingBits) return self._createComponent(asn1Spec, tagSet, value), tail if not self.supportConstructedForm: raise error.PyAsn1Error( 'Constructed encoding form prohibited at %s' % self.__class__.__name__) bitString = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(bitString, substrate, length) while head: component, head = decodeFun(head, self.protoComponent) bitString += component return bitString, tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): substrate = substrate[:length] if not substrate: raise error.PyAsn1Error('Empty substrate') if substrate in self.precomputedValues: value = self.precomputedValues[substrate] else: firstOctet = oct2int(substrate[0]) if firstOctet & 0x80: value = -1 else: value = 0 for octet in substrate: value = value << 8 | oct2int(octet) return self._createComponent(asn1Spec, tagSet, value), substrate
def from_bytes(octets, signed=False): value = long(b2a_hex(str(octets)), 16) if signed and oct2int(octets[0]) & 0x80: return value - (1 << len(octets) * 8) return value
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0), tail if head in self.precomputedValues: value = self.precomputedValues[head] else: firstOctet = oct2int(head[0]) if firstOctet & 0x80: value = -1 else: value = 0 for octet in head: value = value << 8 | oct2int(octet) return self._createComponent(asn1Spec, tagSet, value), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? if not head: raise error.PyAsn1Error('Empty substrate') trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) head = head[1:] value = self.protoComponent.fromOctetString(head, trailingBits) return self._createComponent(asn1Spec, tagSet, value), tail if not self.supportConstructedForm: raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__) bitString = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(bitString, substrate, length) while head: component, head = decodeFun(head, self.protoComponent) bitString += component return bitString, tail
def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if length != 1: raise error.PyAsn1Error('Not single-octet Boolean payload') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk byte = oct2int(chunk[0]) # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1 # in https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf if byte == 0xff: value = 1 elif byte == 0x00: value = 0 else: raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte) yield self._createComponent(asn1Spec, tagSet, value, **options)
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') oid = () index = 0 substrateLen = len(head) while index < substrateLen: subId = oct2int(head[index]) index += 1 if subId < 128: oid = oid + (subId,) elif subId > 128: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128: subId = (subId << 7) + (nextSubId & 0x7F) if index >= substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for sub-OID past %s' % (oid,) ) nextSubId = oct2int(head[index]) index += 1 oid = oid + ((subId << 7) + nextSubId,) 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
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') oid = () index = 0 substrateLen = len(head) while index < substrateLen: subId = oct2int(head[index]) index += 1 if subId < 128: oid = oid + (subId,) elif subId > 128: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128: subId = (subId << 7) + (nextSubId & 0x7F) if index >= substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for sub-OID past %s' % (oid,) ) nextSubId = oct2int(head[index]) index += 1 oid = oid + ((subId << 7) + nextSubId,) 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
def from_bytes(octets, signed=False): if not octets: return 0 value = long(b2a_hex(ensureString(octets)), 16) if signed and oct2int(octets[0]) & 0x80: return value - (1 << len(octets) * 8) return value
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): substrate = substrate[:length] if not substrate: raise error.PyAsn1Error('Empty substrate') byte = oct2int(substrate[0]) if byte == 0xff: value = 1 elif byte == 0x00: value = 0 else: raise error.PyAsn1Error('Boolean CER violation: %s' % byte) return self._createComponent(asn1Spec, tagSet, value), substrate[1:]
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check? if not head: raise error.PyAsn1Error('Empty substrate') trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) head = head[1:] if BITPATTERN: # Use faster method with lookup table p = 0; l = len(head)-1; b = [] while p < l: b.extend(BITPATTERN[oct2int(head[p])]) p += 1 b.extend(BITPATTERN[oct2int(head[p])][0:8-trailingBits]) else: # Use original, slower method lsb = p = 0; l = len(head)-1; b = () while p <= l: if p == l: lsb = trailingBits j = 7 o = oct2int(head[p]) while j >= lsb: b = b + ((o>>j)&0x01,) j = j - 1 p = p + 1 return self._createComponent(asn1Spec, tagSet, b), tail r = self._createComponent(asn1Spec, tagSet, ()) if substrateFun: return substrateFun(r, substrate, length) while head: component, head = decodeFun(head) r = r + component return r, tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head or length != 1: raise error.PyAsn1Error("Not single-octet Boolean payload") byte = oct2int(head[0]) # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1 # in http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf if byte == 0xFF: value = 1 elif byte == 0x00: value = 0 else: raise error.PyAsn1Error("Unexpected Boolean payload: %s" % byte) return self._createComponent(asn1Spec, tagSet, value), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head or length != 1: raise error.PyAsn1Error('Not single-octet Boolean payload') byte = oct2int(head[0]) # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1 # in http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf if byte == 0xff: value = 1 elif byte == 0x00: value = 0 else: raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte) return self._createComponent(asn1Spec, tagSet, value), tail
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): if value.isPlusInfinity(): return int2oct(0x40), 0 if value.isMinusInfinity(): return int2oct(0x41), 0 m, b, e = value if not m: return null, 0 if b == 10: return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0 elif b == 2: fo = 0x80 # binary enoding if m < 0: fo = fo | 0x40 # sign bit m = -m while int(m) != m: # drop floating point m *= 2 e -= 1 while m & 0x1 == 0: # mantissa normalization m >>= 1 e += 1 eo = null while e not in (0, -1): eo = int2oct(e & 0xff) + eo e >>= 8 if e == 0 and eo and oct2int(eo[0]) & 0x80: eo = int2oct(0) + eo n = len(eo) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n // 0xff + 1) + eo po = null while m: po = int2oct(m & 0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, 0 else: raise error.PyAsn1Error('Prohibited Real base %s' % b)
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): if value.isPlusInfinity(): return int2oct(0x40), 0 if value.isMinusInfinity(): return int2oct(0x41), 0 m, b, e = value if not m: return null, 0 if b == 10: return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0 elif b == 2: fo = 0x80 # binary enoding if m < 0: fo = fo | 0x40 # sign bit m = -m while int(m) != m: # drop floating point m *= 2 e -= 1 while m & 0x1 == 0: # mantissa normalization m >>= 1 e += 1 eo = null while e not in (0, -1): eo = int2oct(e&0xff) + eo e >>= 8 if e == 0 and eo and oct2int(eo[0]) & 0x80: eo = int2oct(0) + eo n = len(eo) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n//0xff+1) + eo po = null while m: po = int2oct(m&0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, 0 else: raise error.PyAsn1Error('Prohibited Real base %s' % b)
def prettyOut(self, value): # override asn1 type method """Implements DISPLAY-HINT evaluation""" if self.displayHint and (self.__integer.isSuperTypeOf(self) or self.__unsigned32.isSuperTypeOf(self) or self.__timeticks.isSuperTypeOf(self) or self.__counter32.isSuperTypeOf(self) or self.__counter64.isSuperTypeOf(self)): _ = lambda t, f=0: (t, f) t, f = _(*self.displayHint.split('-')) if t == 'x': return '0x%x' % value elif t == 'd': try: return '%.*f' % (int(f), float(value) / pow(10, int(f))) except Exception: raise SmiError('float num evaluation error: %s' % sys.exc_info()[1]) elif t == 'o': return '0%o' % value elif t == 'b': v = value r = ['B'] while v: r.insert(0, '%d' % (v & 0x01)) v >>= 1 return ''.join(r) else: raise SmiError('Unsupported numeric type spec: %s' % t) elif self.displayHint and self.__octetString.isSuperTypeOf(self): r = '' v = self.__class__(value).asOctets() d = self.displayHint while v and d: # 1 if d[0] == '*': repeatIndicator = repeatCount = octets.oct2int(v[0]) d = d[1:] v = v[1:] else: repeatCount = 1 repeatIndicator = None # 2 octetLength = '' while d and d[0] in '0123456789': octetLength += d[0] d = d[1:] try: octetLength = int(octetLength) except Exception: raise SmiError('Bad octet length: %s' % octetLength) if not d: raise SmiError('Short octet length: %s' % self.displayHint) # 3 displayFormat = d[0] d = d[1:] # 4 if d and d[0] not in '0123456789' and d[0] != '*': displaySep = d[0] d = d[1:] else: displaySep = '' # 5 if d and displaySep and repeatIndicator is not None: repeatTerminator = d[0] displaySep = '' d = d[1:] else: repeatTerminator = None while repeatCount: repeatCount -= 1 if displayFormat == 'a': r += v[:octetLength].decode('ascii', 'ignore') elif displayFormat == 't': r += v[:octetLength].decode('utf-8', 'ignore') elif displayFormat in ('x', 'd', 'o'): n = 0 vv = v[:octetLength] while vv: n <<= 8 try: n |= octets.oct2int(vv[0]) vv = vv[1:] except Exception: raise SmiError( 'Display format eval failure: %s: %s' % (vv, sys.exc_info()[1])) if displayFormat == 'x': r += '%02x' % n elif displayFormat == 'o': r += '%03o' % n else: r += '%d' % n else: raise SmiError('Unsupported display format char: %s' % displayFormat) if v and repeatTerminator: r += repeatTerminator v = v[octetLength:] if v and displaySep: r += displaySep if not d: d = self.displayHint # if d: # raise SmiError( # 'Unparsed display hint left: %s' % d # ) return r elif self.__objectIdentifier.isSuperTypeOf(self): return self.__objectIdentifier.prettyOut(value) elif self.__octetString.isSuperTypeOf(self): return self.__octetString.prettyOut(value) else: return str(value)
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=1): fullSubstrate = substrate while state != stStop: if state == stDecodeTag: # Decode tag if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding' ) firstOctet = substrate[0] substrate = substrate[1:] if firstOctet in self.__tagCache: lastTag = self.__tagCache[firstOctet] else: t = oct2int(firstOctet) tagClass = t&0xC0 tagFormat = t&0x20 tagId = t&0x1F if tagId == 0x1F: tagId = 0 while 1: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding' ) t = oct2int(substrate[0]) tagId = tagId << 7 | (t&0x7F) substrate = substrate[1:] if not t&0x80: break lastTag = tag.Tag( tagClass=tagClass, tagFormat=tagFormat, tagId=tagId ) if tagId < 31: # cache short tags self.__tagCache[firstOctet] = lastTag if tagSet is None: if firstOctet in self.__tagSetCache: tagSet = self.__tagSetCache[firstOctet] else: # base tag not recovered tagSet = tag.TagSet((), lastTag) if firstOctet in self.__tagCache: self.__tagSetCache[firstOctet] = tagSet else: tagSet = lastTag + tagSet state = stDecodeLength if state == stDecodeLength: # Decode length if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding' ) firstOctet = oct2int(substrate[0]) if firstOctet == 128: size = 1 length = -1 elif firstOctet < 128: length, size = firstOctet, 1 else: size = firstOctet & 0x7F # encoded in size bytes length = 0 lengthString = substrate[1:size+1] # missing check on maximum size, which shouldn't be a # problem, we can handle more than is possible if len(lengthString) != size: raise error.SubstrateUnderrunError( '%s<%s at %s' % (size, len(lengthString), tagSet) ) for char in lengthString: length = (length << 8) | oct2int(char) size = size + 1 state = stGetValueDecoder substrate = substrate[size:] if length != -1 and len(substrate) < length: raise error.SubstrateUnderrunError( '%d-octet short' % (length - len(substrate)) ) if state == stGetValueDecoder: if asn1Spec is None: state = stGetValueDecoderByTag else: state = stGetValueDecoderByAsn1Spec # # There're two ways of creating subtypes in ASN.1 what influences # decoder operation. These methods are: # 1) Either base types used in or no IMPLICIT tagging has been # applied on subtyping. # 2) Subtype syntax drops base type information (by means of # IMPLICIT tagging. # The first case allows for complete tag recovery from substrate # while the second one requires original ASN.1 type spec for # decoding. # # In either case a set of tags (tagSet) is coming from substrate # in an incremental, tag-by-tag fashion (this is the case of # EXPLICIT tag which is most basic). Outermost tag comes first # from the wire. # if state == stGetValueDecoderByTag: if tagSet in self.__tagMap: concreteDecoder = self.__tagMap[tagSet] else: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: _k = tagSet[:1] if _k in self.__tagMap: concreteDecoder = self.__tagMap[_k] else: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: state = stTryAsExplicitTag if state == stGetValueDecoderByAsn1Spec: if isinstance(asn1Spec, (dict, tagmap.TagMap)): if tagSet in asn1Spec: __chosenSpec = asn1Spec[tagSet] else: __chosenSpec = None else: __chosenSpec = asn1Spec if __chosenSpec is not None and ( tagSet == __chosenSpec.getTagSet() or \ tagSet in __chosenSpec.getTagMap() ): # use base type for codec lookup to recover untagged types baseTagSet = __chosenSpec.baseTagSet if __chosenSpec.typeId is not None and \ __chosenSpec.typeId in self.__typeMap: # ambiguous type concreteDecoder = self.__typeMap[__chosenSpec.typeId] elif baseTagSet in self.__tagMap: # base type or tagged subtype concreteDecoder = self.__tagMap[baseTagSet] else: concreteDecoder = None if concreteDecoder: asn1Spec = __chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag elif tagSet == self.__endOfOctetsTagSet: concreteDecoder = self.__tagMap[tagSet] state = stDecodeValue else: state = stTryAsExplicitTag if state == stTryAsExplicitTag: if tagSet and \ tagSet[0][1] == tag.tagFormatConstructed and \ tagSet[0][0] != tag.tagClassUniversal: # Assume explicit tagging concreteDecoder = explicitTagDecoder state = stDecodeValue else: state = self.defaultErrorState if state == stDumpRawValue: concreteDecoder = self.defaultRawDecoder state = stDecodeValue if state == stDecodeValue: if recursiveFlag: decodeFun = self else: decodeFun = None if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, decodeFun ) else: value, _substrate = concreteDecoder.valueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, decodeFun ) if recursiveFlag: substrate = substrate[length:] else: substrate = _substrate state = stStop if state == stErrorCondition: raise error.PyAsn1Error( '%s not in asn1Spec: %s' % (tagSet, repr(asn1Spec)) ) return value, substrate
def test_oct2int(self): assert 12 == octets.oct2int(bytes([12]))[0]
def prettyOut(self, value): # override asn1 type method """Implements DISPLAY-HINT evaluation""" if self.displayHint and (self.__integer.isSuperTypeOf(self, matchConstraints=False) and not self.getNamedValues() or self.__unsigned32.isSuperTypeOf(self, matchConstraints=False) or self.__timeticks.isSuperTypeOf(self, matchConstraints=False)): _ = lambda t, f=0: (t, f) displayHintType, decimalPrecision = _(*self.displayHint.split('-')) if displayHintType == 'x': return '0x%x' % value elif displayHintType == 'd': try: return '%.*f' % (int(decimalPrecision), float(value) / pow(10, int(decimalPrecision))) except Exception as exc: raise SmiError( 'float evaluation error: %s' % exc ) elif displayHintType == 'o': return '0%o' % value elif displayHintType == 'b': runningValue = value outputValue = ['B'] while runningValue: outputValue.insert(0, '%d' % (runningValue & 0x01)) runningValue >>= 1 return ''.join(outputValue) else: raise SmiError( 'Unsupported numeric type spec "%s" at %s' % (displayHintType, self.__class__.__name__) ) elif self.displayHint and self.__octetString.isSuperTypeOf(self, matchConstraints=False): outputValue = '' runningValue = OctetString(value).asOctets() displayHint = self.displayHint while runningValue and displayHint: # 1 if displayHint[0] == '*': repeatIndicator = repeatCount = octets.oct2int(runningValue[0]) displayHint = displayHint[1:] runningValue = runningValue[1:] else: repeatCount = 1 repeatIndicator = None # 2 octetLength = '' while displayHint and displayHint[0] in string.digits: octetLength += displayHint[0] displayHint = displayHint[1:] # length is manatory, but people ignore that if not octetLength: octetLength = len(runningValue) try: octetLength = int(octetLength) except Exception: raise SmiError( 'Bad octet length: %s' % octetLength ) if not displayHint: raise SmiError( 'Short octet length: %s' % self.displayHint ) # 3 displayFormat = displayHint[0] displayHint = displayHint[1:] # 4 if displayHint and displayHint[0] not in string.digits and displayHint[0] != '*': displaySep = displayHint[0] displayHint = displayHint[1:] else: displaySep = '' # 5 if displayHint and displaySep and repeatIndicator is not None: repeatTerminator = displayHint[0] displaySep = '' displayHint = displayHint[1:] else: repeatTerminator = None while repeatCount: repeatCount -= 1 if displayFormat == 'a': outputValue += runningValue[:octetLength].decode('ascii', 'ignore') elif displayFormat == 't': outputValue += runningValue[:octetLength].decode('utf-8', 'ignore') elif displayFormat in ('x', 'd', 'o'): number = 0 numberString = runningValue[:octetLength] while numberString: number <<= 8 try: number |= octets.oct2int(numberString[0]) numberString = numberString[1:] except Exception as exc: raise SmiError( 'Display format eval failure: %s: %s' % (numberString, exc) ) if displayFormat == 'x': outputValue += '%02x' % number elif displayFormat == 'o': outputValue += '%03o' % number else: outputValue += '%d' % number else: raise SmiError( 'Unsupported display format char: %s' % displayFormat ) if runningValue and repeatTerminator: outputValue += repeatTerminator runningValue = runningValue[octetLength:] if runningValue and displaySep: outputValue += displaySep if not displayHint: displayHint = self.displayHint return outputValue for base in inspect.getmro(self.__class__): if not issubclass(base, TextualConvention) and issubclass(base, Asn1Item): return base.prettyOut(self, value) raise SmiError('TEXTUAL-CONVENTION has no underlying SNMP base type')
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=True, substrateFun=None, allowEoo=False): if debug.logger and 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))) substrate = ensureString(substrate) # Look for end-of-octets sentinel if allowEoo and self.supportIndefLength: if substrate.startswith(self.__eooSentinel): debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets sentinel found') return eoo.endOfOctets, substrate[2:] value = base.noValue fullSubstrate = substrate while state != stStop: if state == stDecodeTag: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding' ) # Decode tag isShortTag = True firstOctet = substrate[0] substrate = substrate[1:] try: lastTag = self.__tagCache[firstOctet] except KeyError: integerTag = oct2int(firstOctet) tagClass = integerTag & 0xC0 tagFormat = integerTag & 0x20 tagId = integerTag & 0x1F if tagId == 0x1F: isShortTag = False lengthOctetIdx = 0 tagId = 0 try: while True: integerTag = oct2int(substrate[lengthOctetIdx]) lengthOctetIdx += 1 tagId <<= 7 tagId |= (integerTag & 0x7F) if not integerTag & 0x80: break substrate = substrate[lengthOctetIdx:] except IndexError: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding' ) lastTag = tag.Tag( tagClass=tagClass, tagFormat=tagFormat, tagId=tagId ) if isShortTag: # cache short tags self.__tagCache[firstOctet] = lastTag if tagSet is None: if isShortTag: try: tagSet = self.__tagSetCache[firstOctet] except KeyError: # base tag not recovered tagSet = tag.TagSet((), lastTag) self.__tagSetCache[firstOctet] = tagSet else: tagSet = tag.TagSet((), lastTag) else: tagSet = lastTag + tagSet state = stDecodeLength debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'tag decoded into %s, decoding length' % tagSet) if state == stDecodeLength: # Decode length if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding' ) firstOctet = oct2int(substrate[0]) if firstOctet < 128: size = 1 length = firstOctet elif firstOctet == 128: size = 1 length = -1 else: size = firstOctet & 0x7F # encoded in size bytes encodedLength = octs2ints(substrate[1:size + 1]) # missing check on maximum size, which shouldn't be a # problem, we can handle more than is possible if len(encodedLength) != size: raise error.SubstrateUnderrunError( '%s<%s at %s' % (size, len(encodedLength), tagSet) ) length = 0 for lengthOctet in encodedLength: length <<= 8 length |= lengthOctet size += 1 substrate = substrate[size:] if length == -1: if not self.supportIndefLength: raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') else: if len(substrate) < length: raise error.SubstrateUnderrunError('%d-octet short' % (length - len(substrate))) 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])) ) if state == stGetValueDecoder: if asn1Spec is None: state = stGetValueDecoderByTag else: state = stGetValueDecoderByAsn1Spec # # There're two ways of creating subtypes in ASN.1 what influences # decoder operation. These methods are: # 1) Either base types used in or no IMPLICIT tagging has been # applied on subtyping. # 2) Subtype syntax drops base type information (by means of # IMPLICIT tagging. # The first case allows for complete tag recovery from substrate # while the second one requires original ASN.1 type spec for # decoding. # # In either case a set of tags (tagSet) is coming from substrate # in an incremental, tag-by-tag fashion (this is the case of # EXPLICIT tag which is most basic). Outermost tag comes first # from the wire. # if state == stGetValueDecoderByTag: try: concreteDecoder = self.__tagMap[tagSet] except KeyError: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: try: concreteDecoder = self.__tagMap[tagSet[:1]] except KeyError: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: state = stTryAsExplicitTag if debug.logger and debug.logger & debug.flagDecoder: debug.logger('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push( concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__) if state == stGetValueDecoderByAsn1Spec: if asn1Spec.__class__ is dict or asn1Spec.__class__ is tagmap.TagMap: try: chosenSpec = asn1Spec[tagSet] except KeyError: chosenSpec = None if debug.logger and debug.logger & debug.flagDecoder: debug.logger('candidate ASN.1 spec is a map of:') for firstOctet, v in asn1Spec.presentTypes.items(): debug.logger(' %s -> %s' % (firstOctet, v.__class__.__name__)) if asn1Spec.skipTypes: debug.logger('but neither of: ') for firstOctet, v in asn1Spec.skipTypes.items(): debug.logger(' %s -> %s' % (firstOctet, v.__class__.__name__)) debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet)) else: if tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap: chosenSpec = asn1Spec debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) else: chosenSpec = None if chosenSpec is not None: try: # ambiguous type or just faster codec lookup concreteDecoder = self.__typeMap[chosenSpec.typeId] debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId,)) except KeyError: # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag, chosenSpec.tagSet.baseTag) try: # base type or tagged subtype concreteDecoder = self.__tagMap[baseTagSet] debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'value decoder chosen by base %s' % (baseTagSet,)) except KeyError: concreteDecoder = None if concreteDecoder: asn1Spec = chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag else: concreteDecoder = None state = stTryAsExplicitTag if debug.logger and debug.logger & debug.flagDecoder: debug.logger('codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__) if state == stTryAsExplicitTag: if tagSet and tagSet[0].tagFormat == tag.tagFormatConstructed and tagSet[0].tagClass != tag.tagClassUniversal: # Assume explicit tagging concreteDecoder = explicitTagDecoder state = stDecodeValue else: concreteDecoder = None state = self.defaultErrorState debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure')) if state == stDumpRawValue: concreteDecoder = self.defaultRawDecoder debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'codec %s chosen, decoding value' % concreteDecoder.__class__.__name__) state = stDecodeValue if state == stDecodeValue: if not recursiveFlag and not substrateFun: # legacy def substrateFun(a, b, c): return a, b[:c] if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun ) else: value, substrate = concreteDecoder.valueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun ) state = stStop 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: raise error.PyAsn1Error( '%s not in asn1Spec: %s' % (tagSet, asn1Spec) ) if debug.logger and debug.logger & debug.flagDecoder: debug.scope.pop() debug.logger('decoder left scope %s, call completed' % debug.scope) return value, substrate
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=True, substrateFun=None, allowEoo=False): if debug.logger & debug.flagDecoder: logger = debug.logger else: logger = None if logger: 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))) substrate = ensureString(substrate) # Look for end-of-octets sentinel if allowEoo and self.supportIndefLength: if substrate.startswith(self.__eooSentinel): if logger: logger('end-of-octets sentinel found') return eoo.endOfOctets, substrate[2:] value = base.noValue fullSubstrate = substrate while not state is stStop: if state is stDecodeTag: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding') # Decode tag isShortTag = True firstOctet = substrate[0] substrate = substrate[1:] try: lastTag = self.__tagCache[firstOctet] except KeyError: integerTag = oct2int(firstOctet) tagClass = integerTag & 0xC0 tagFormat = integerTag & 0x20 tagId = integerTag & 0x1F if tagId == 0x1F: isShortTag = False lengthOctetIdx = 0 tagId = 0 try: while True: integerTag = oct2int(substrate[lengthOctetIdx]) lengthOctetIdx += 1 tagId <<= 7 tagId |= (integerTag & 0x7F) if not integerTag & 0x80: break substrate = substrate[lengthOctetIdx:] except IndexError: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding') lastTag = tag.Tag(tagClass=tagClass, tagFormat=tagFormat, tagId=tagId) if isShortTag: # cache short tags self.__tagCache[firstOctet] = lastTag if tagSet is None: if isShortTag: try: tagSet = self.__tagSetCache[firstOctet] except KeyError: # base tag not recovered tagSet = tag.TagSet((), lastTag) self.__tagSetCache[firstOctet] = tagSet else: tagSet = tag.TagSet((), lastTag) else: tagSet = lastTag + tagSet state = stDecodeLength if logger: logger('tag decoded into %s, decoding length' % tagSet) if state is stDecodeLength: # Decode length if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding') firstOctet = oct2int(substrate[0]) if firstOctet < 128: size = 1 length = firstOctet elif firstOctet == 128: size = 1 length = -1 else: size = firstOctet & 0x7F # encoded in size bytes encodedLength = octs2ints(substrate[1:size + 1]) # missing check on maximum size, which shouldn't be a # problem, we can handle more than is possible if len(encodedLength) != size: raise error.SubstrateUnderrunError( '%s<%s at %s' % (size, len(encodedLength), tagSet)) length = 0 for lengthOctet in encodedLength: length <<= 8 length |= lengthOctet size += 1 substrate = substrate[size:] if length == -1: if not self.supportIndefLength: raise error.PyAsn1Error( 'Indefinite length encoding not supported by this codec' ) else: if len(substrate) < length: raise error.SubstrateUnderrunError( '%d-octet short' % (length - len(substrate))) state = stGetValueDecoder if logger: logger( 'value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length]))) if state is stGetValueDecoder: if asn1Spec is None: state = stGetValueDecoderByTag else: state = stGetValueDecoderByAsn1Spec # # There're two ways of creating subtypes in ASN.1 what influences # decoder operation. These methods are: # 1) Either base types used in or no IMPLICIT tagging has been # applied on subtyping. # 2) Subtype syntax drops base type information (by means of # IMPLICIT tagging. # The first case allows for complete tag recovery from substrate # while the second one requires original ASN.1 type spec for # decoding. # # In either case a set of tags (tagSet) is coming from substrate # in an incremental, tag-by-tag fashion (this is the case of # EXPLICIT tag which is most basic). Outermost tag comes first # from the wire. # if state is stGetValueDecoderByTag: try: concreteDecoder = self.__tagMap[tagSet] except KeyError: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: try: concreteDecoder = self.__tagMap[tagSet[:1]] except KeyError: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: state = stTryAsExplicitTag if logger: logger( 'codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push( concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__) if state is stGetValueDecoderByAsn1Spec: if asn1Spec.__class__ is dict or asn1Spec.__class__ is tagmap.TagMap: try: chosenSpec = asn1Spec[tagSet] except KeyError: chosenSpec = None if logger: logger('candidate ASN.1 spec is a map of:') for firstOctet, v in asn1Spec.presentTypes.items(): logger(' %s -> %s' % (firstOctet, v.__class__.__name__)) if asn1Spec.skipTypes: logger('but neither of: ') for firstOctet, v in asn1Spec.skipTypes.items(): logger(' %s -> %s' % (firstOctet, v.__class__.__name__)) logger('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet)) else: if tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap: chosenSpec = asn1Spec if logger: logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) else: chosenSpec = None if chosenSpec is not None: try: # ambiguous type or just faster codec lookup concreteDecoder = self.__typeMap[chosenSpec.typeId] if logger: logger( 'value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId, )) except KeyError: # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag, chosenSpec.tagSet.baseTag) try: # base type or tagged subtype concreteDecoder = self.__tagMap[baseTagSet] if logger: logger('value decoder chosen by base %s' % (baseTagSet, )) except KeyError: concreteDecoder = None if concreteDecoder: asn1Spec = chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag else: concreteDecoder = None state = stTryAsExplicitTag if logger: logger('codec %s chosen by ASN.1 spec, decoding %s' % (state is stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__) if state is stTryAsExplicitTag: if tagSet and tagSet[ 0].tagFormat == tag.tagFormatConstructed and tagSet[ 0].tagClass != tag.tagClassUniversal: # Assume explicit tagging concreteDecoder = explicitTagDecoder state = stDecodeValue else: concreteDecoder = None state = self.defaultErrorState if logger: logger( 'codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as failure')) if state is stDumpRawValue: concreteDecoder = self.defaultRawDecoder if logger: logger('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__) state = stDecodeValue if state is stDecodeValue: if not recursiveFlag and not substrateFun: # legacy def substrateFun(a, b, c): return a, b[:c] if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun) else: value, substrate = concreteDecoder.valueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun) state = stStop if logger: 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 is stErrorCondition: raise error.PyAsn1Error('%s not in asn1Spec: %r' % (tagSet, asn1Spec)) if logger: debug.scope.pop() logger('decoder left scope %s, call completed' % debug.scope) return value, substrate
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=1, substrateFun=None, allowEoo=False): 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))) if asn1Spec is not None and not isinstance(asn1Spec, (base.Asn1Item, tagmap.TagMap)): raise error.PyAsn1Error('asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__) fullSubstrate = substrate while state != stStop: if state == stDecodeTag: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding' ) if not isOctetsType(substrate) and \ not isinstance(substrate, univ.OctetString): raise error.PyAsn1Error('Bad octet stream type') # Decode tag firstOctet = substrate[0] substrate = substrate[1:] if firstOctet in self.__tagCache: lastTag = self.__tagCache[firstOctet] else: 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 tagFormat = t&0x20 tagId = t&0x1F if tagId == 0x1F: tagId = 0 while 1: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding' ) t = oct2int(substrate[0]) tagId = tagId << 7 | (t&0x7F) substrate = substrate[1:] if not t&0x80: break lastTag = tag.Tag( tagClass=tagClass, tagFormat=tagFormat, tagId=tagId ) if tagId < 31: # cache short tags self.__tagCache[firstOctet] = lastTag if tagSet is None: if firstOctet in self.__tagSetCache: tagSet = self.__tagSetCache[firstOctet] else: # base tag not recovered tagSet = tag.TagSet((), lastTag) if firstOctet in self.__tagCache: self.__tagSetCache[firstOctet] = tagSet else: tagSet = lastTag + tagSet state = stDecodeLength debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %s, decoding length' % tagSet) if state == stDecodeLength: # Decode length if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding' ) firstOctet = oct2int(substrate[0]) if firstOctet == 128: size = 1 length = -1 elif firstOctet < 128: length, size = firstOctet, 1 else: size = firstOctet & 0x7F # encoded in size bytes length = 0 lengthString = substrate[1:size+1] # missing check on maximum size, which shouldn't be a # problem, we can handle more than is possible if len(lengthString) != size: raise error.SubstrateUnderrunError( '%s<%s at %s' % (size, len(lengthString), tagSet) ) for char in lengthString: length = (length << 8) | oct2int(char) size += 1 substrate = substrate[size:] if length != -1 and len(substrate) < length: raise error.SubstrateUnderrunError( '%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 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 asn1Spec is None: state = stGetValueDecoderByTag else: state = stGetValueDecoderByAsn1Spec # # There're two ways of creating subtypes in ASN.1 what influences # decoder operation. These methods are: # 1) Either base types used in or no IMPLICIT tagging has been # applied on subtyping. # 2) Subtype syntax drops base type information (by means of # IMPLICIT tagging. # The first case allows for complete tag recovery from substrate # while the second one requires original ASN.1 type spec for # decoding. # # In either case a set of tags (tagSet) is coming from substrate # in an incremental, tag-by-tag fashion (this is the case of # EXPLICIT tag which is most basic). Outermost tag comes first # from the wire. # if state == stGetValueDecoderByTag: if tagSet in self.__tagMap: concreteDecoder = self.__tagMap[tagSet] else: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: _k = tagSet[:1] if _k in self.__tagMap: concreteDecoder = self.__tagMap[_k] else: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: state = stTryAsExplicitTag if debug.logger and debug.logger & debug.flagDecoder: debug.logger('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__) if state == stGetValueDecoderByAsn1Spec: if isinstance(asn1Spec, (dict, tagmap.TagMap)): if tagSet in asn1Spec: __chosenSpec = asn1Spec[tagSet] else: __chosenSpec = None if debug.logger and debug.logger & debug.flagDecoder: debug.logger('candidate ASN.1 spec is a map of:') for t, v in asn1Spec.getPosMap().items(): debug.logger(' %s -> %s' % (t, v.__class__.__name__)) if asn1Spec.getNegMap(): debug.logger('but neither of: ') for t, v in asn1Spec.getNegMap().items(): debug.logger(' %s -> %s' % (t, v.__class__.__name__)) debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (__chosenSpec is None and '<none>' or __chosenSpec.prettyPrintType(), tagSet)) else: __chosenSpec = asn1Spec debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) if __chosenSpec is not None and ( tagSet == __chosenSpec.getTagSet() or \ tagSet in __chosenSpec.getTagMap() ): # use base type for codec lookup to recover untagged types baseTagSet = __chosenSpec.baseTagSet if __chosenSpec.typeId is not None and \ __chosenSpec.typeId in self.__typeMap: # ambiguous type concreteDecoder = self.__typeMap[__chosenSpec.typeId] debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen for an ambiguous type by type ID %s' % (__chosenSpec.typeId,)) elif baseTagSet in self.__tagMap: # base type or tagged subtype concreteDecoder = self.__tagMap[baseTagSet] debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %s' % (baseTagSet,)) else: concreteDecoder = None if concreteDecoder: asn1Spec = __chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag else: concreteDecoder = None state = stTryAsExplicitTag if debug.logger and debug.logger & debug.flagDecoder: debug.logger('codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(__chosenSpec is None and '?' or __chosenSpec.__class__.__name__) if state == stTryAsExplicitTag: if tagSet and \ tagSet[0][1] == tag.tagFormatConstructed and \ tagSet[0][0] != tag.tagClassUniversal: # Assume explicit tagging concreteDecoder = explicitTagDecoder state = stDecodeValue else: concreteDecoder = None state = self.defaultErrorState debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure')) if state == stDumpRawValue: concreteDecoder = self.defaultRawDecoder debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__) state = stDecodeValue if state == stDecodeValue: if recursiveFlag == 0 and not substrateFun: # legacy substrateFun = lambda a,b,c: (a,b[:c]) if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun ) else: value, substrate = concreteDecoder.valueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun ) state = stStop 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: raise error.PyAsn1Error( '%s not in asn1Spec: %s' % (tagSet, asn1Spec) ) if debug.logger and debug.logger & debug.flagDecoder: debug.scope.pop() debug.logger('decoder left scope %s, call completed' % debug.scope) return value, substrate
def test_oct2int(self): assert 12 == octets.oct2int('\x0c')
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): if value.isPlusInfinity(): return int2oct(0x40), 0 if value.isMinusInfinity(): return int2oct(0x41), 0 m, b, e = value if not m: return null, 0 if b == 10: return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0 elif b == 2: fo = 0x80 # binary encoding ms, m, encbase, e = self._chooseEncBase(value) if ms < 0: # mantissa sign fo = fo | 0x40 # sign bit # exponenta & mantissa normalization if encbase == 2: while m & 0x1 == 0: 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 sf += 1 if sf > 3: raise error.PyAsn1Error('Scale factor overflow') # bug if raised fo |= sf << 2 eo = null if e == 0 or e == -1: eo = int2oct(e&0xff) else: while e not in (0, -1): 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) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n&0xff) + eo po = null while m: po = int2oct(m&0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, 0 else: raise error.PyAsn1Error('Prohibited Real base %s' % b)
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): if value.isPlusInfinity(): return int2oct(0x40), 0 if value.isMinusInfinity(): return int2oct(0x41), 0 m, b, e = value if not m: return null, 0 if b == 10: return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0 elif b == 2: fo = 0x80 # binary encoding ms, m, encbase, e = self._chooseEncBase(value) if ms < 0: # mantissa sign fo = fo | 0x40 # sign bit # exponenta & mantissa normalization if encbase == 2: while m & 0x1 == 0: 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 sf += 1 if sf > 3: raise error.PyAsn1Error( 'Scale factor overflow') # bug if raised fo |= sf << 2 eo = null if e == 0 or e == -1: eo = int2oct(e & 0xff) else: while e not in (0, -1): 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) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n & 0xff) + eo po = null while m: po = int2oct(m & 0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, 0 else: raise error.PyAsn1Error('Prohibited Real base %s' % b)
def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is not None: value = asn1Spec.clone(value) if value.isPlusInf: return (0x40, ), False, False if value.isMinusInf: return (0x41, ), False, False m, b, e = value if not m: return null, False, True if b == 10: if LOG: LOG('encoding REAL into character form') return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True elif b == 2: fo = 0x80 # binary encoding ms, m, encbase, e = self._chooseEncBase(value) if ms < 0: # mantissa sign fo |= 0x40 # sign bit # exponent & mantissa normalization if encbase == 2: while m & 0x1 == 0: 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 sf += 1 if sf > 3: raise error.PyAsn1Error( 'Scale factor overflow') # bug if raised fo |= sf << 2 eo = null if e == 0 or e == -1: eo = int2oct(e & 0xff) else: while e not in (0, -1): 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) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n & 0xff) + eo po = null while m: po = int2oct(m & 0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, False, True else: raise error.PyAsn1Error('Prohibited Real base %s' % b)
def prettyOut(self, value): # override asn1 type method """Implements DISPLAY-HINT evaluation""" if self.displayHint and (self.__integer.isSuperTypeOf(self) or self.__unsigned32.isSuperTypeOf(self) or self.__timeticks.isSuperTypeOf(self) or self.__counter32.isSuperTypeOf(self) or self.__counter64.isSuperTypeOf(self)): _ = lambda t, f=0: (t, f) t, f = _(*self.displayHint.split('-')) if t == 'x': return '0x%x' % value elif t == 'd': try: return '%.*f' % (int(f), float(value) / pow(10, int(f))) except Exception: raise SmiError( 'float num evaluation error: %s' % sys.exc_info()[1] ) elif t == 'o': return '0%o' % value elif t == 'b': v = value r = ['B'] while v: r.insert(0, '%d' % (v & 0x01)) v >>= 1 return ''.join(r) else: raise SmiError( 'Unsupported numeric type spec: %s' % t ) elif self.displayHint and self.__octetString.isSuperTypeOf(self): r = '' v = self.__class__(value).asOctets() d = self.displayHint while v and d: # 1 if d[0] == '*': repeatIndicator = repeatCount = octets.oct2int(v[0]) d = d[1:] v = v[1:] else: repeatCount = 1 repeatIndicator = None # 2 octetLength = '' while d and d[0] in '0123456789': octetLength += d[0] d = d[1:] try: octetLength = int(octetLength) except Exception: raise SmiError( 'Bad octet length: %s' % octetLength ) if not d: raise SmiError( 'Short octet length: %s' % self.displayHint ) # 3 displayFormat = d[0] d = d[1:] # 4 if d and d[0] not in '0123456789' and d[0] != '*': displaySep = d[0] d = d[1:] else: displaySep = '' # 5 if d and displaySep and repeatIndicator is not None: repeatTerminator = d[0] displaySep = '' d = d[1:] else: repeatTerminator = None while repeatCount: repeatCount -= 1 if displayFormat == 'a': r += v[:octetLength].decode('ascii', 'ignore') elif displayFormat == 't': r += v[:octetLength].decode('utf-8', 'ignore') elif displayFormat in ('x', 'd', 'o'): n = 0 vv = v[:octetLength] while vv: n <<= 8 try: n |= octets.oct2int(vv[0]) vv = vv[1:] except Exception: raise SmiError( 'Display format eval failure: %s: %s' % (vv, sys.exc_info()[1]) ) if displayFormat == 'x': r += '%02x' % n elif displayFormat == 'o': r += '%03o' % n else: r += '%d' % n else: raise SmiError( 'Unsupported display format char: %s' % displayFormat ) if v and repeatTerminator: r += repeatTerminator v = v[octetLength:] if v and displaySep: r += displaySep if not d: d = self.displayHint # if d: # raise SmiError( # 'Unparsed display hint left: %s' % d # ) return r elif self.__objectIdentifier.isSuperTypeOf(self): return self.__objectIdentifier.prettyOut(value) elif self.__octetString.isSuperTypeOf(self): return self.__octetString.prettyOut(value) else: return str(value)
def prettyOut(self, value): # override asn1 type method """Implements DISPLAY-HINT evaluation""" if self.displayHint and (self.__integer.isSuperTypeOf( self, matchConstraints=False) and not self.getNamedValues() or self.__unsigned32.isSuperTypeOf( self, matchConstraints=False) or self.__timeticks.isSuperTypeOf( self, matchConstraints=False)): _ = lambda t, f=0: (t, f) displayHintType, decimalPrecision = _(*self.displayHint.split('-')) if displayHintType == 'x': return '0x%x' % value elif displayHintType == 'd': try: return '%.*f' % (int(decimalPrecision), float(value) / pow(10, int(decimalPrecision))) except Exception: raise SmiError('float evaluation error: %s' % sys.exc_info()[1]) elif displayHintType == 'o': return '0%o' % value elif displayHintType == 'b': runningValue = value outputValue = ['B'] while runningValue: outputValue.insert(0, '%d' % (runningValue & 0x01)) runningValue >>= 1 return ''.join(outputValue) else: raise SmiError('Unsupported numeric type spec "%s" at %s' % (displayHintType, self.__class__.__name__)) elif self.displayHint and self.__octetString.isSuperTypeOf( self, matchConstraints=False): outputValue = '' runningValue = OctetString(value).asOctets() displayHint = self.displayHint while runningValue and displayHint: # 1 if displayHint[0] == '*': repeatIndicator = repeatCount = octets.oct2int( runningValue[0]) displayHint = displayHint[1:] runningValue = runningValue[1:] else: repeatCount = 1 repeatIndicator = None # 2 octetLength = '' while displayHint and displayHint[0] in string.digits: octetLength += displayHint[0] displayHint = displayHint[1:] # length is manatory, but people ignore that if not octetLength: octetLength = len(runningValue) try: octetLength = int(octetLength) except Exception: raise SmiError('Bad octet length: %s' % octetLength) if not displayHint: raise SmiError('Short octet length: %s' % self.displayHint) # 3 displayFormat = displayHint[0] displayHint = displayHint[1:] # 4 if displayHint and displayHint[ 0] not in string.digits and displayHint[0] != '*': displaySep = displayHint[0] displayHint = displayHint[1:] else: displaySep = '' # 5 if displayHint and displaySep and repeatIndicator is not None: repeatTerminator = displayHint[0] displaySep = '' displayHint = displayHint[1:] else: repeatTerminator = None while repeatCount: repeatCount -= 1 if displayFormat == 'a': outputValue += runningValue[:octetLength].decode( 'ascii', 'ignore') elif displayFormat == 't': outputValue += runningValue[:octetLength].decode( 'utf-8', 'ignore') elif displayFormat in ('x', 'd', 'o'): number = 0 numberString = runningValue[:octetLength] while numberString: number <<= 8 try: number |= octets.oct2int(numberString[0]) numberString = numberString[1:] except Exception: raise SmiError( 'Display format eval failure: %s: %s' % (numberString, sys.exc_info()[1])) if displayFormat == 'x': outputValue += '%02x' % number elif displayFormat == 'o': outputValue += '%03o' % number else: outputValue += '%d' % number else: raise SmiError('Unsupported display format char: %s' % displayFormat) if runningValue and repeatTerminator: outputValue += repeatTerminator runningValue = runningValue[octetLength:] if runningValue and displaySep: outputValue += displaySep if not displayHint: displayHint = self.displayHint return outputValue for base in inspect.getmro(self.__class__): if not issubclass(base, TextualConvention) and issubclass( base, Asn1Item): return base.prettyOut(self, value) raise SmiError('TEXTUAL-CONVENTION has no underlying SNMP base type')
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=1, substrateFun=None, allowEoo=False): 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))) if asn1Spec is not None and not isinstance( asn1Spec, (base.Asn1Item, tagmap.TagMap)): raise error.PyAsn1Error( 'asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__) value = base.noValue fullSubstrate = substrate while state != stStop: if state == stDecodeTag: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding') if not isOctetsType(substrate) and \ not isinstance(substrate, univ.OctetString): raise error.PyAsn1Error('Bad octet stream type') # Decode tag firstOctet = substrate[0] substrate = substrate[1:] if firstOctet in self.__tagCache: lastTag = self.__tagCache[firstOctet] else: 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 tagFormat = t & 0x20 tagId = t & 0x1F short = True if tagId == 0x1F: short = False tagId = 0 while True: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding') t = oct2int(substrate[0]) tagId = tagId << 7 | (t & 0x7F) substrate = substrate[1:] if not t & 0x80: break lastTag = tag.Tag(tagClass=tagClass, tagFormat=tagFormat, tagId=tagId) if short: # cache short tags self.__tagCache[firstOctet] = lastTag if tagSet is None: if firstOctet in self.__tagSetCache: tagSet = self.__tagSetCache[firstOctet] else: # base tag not recovered tagSet = tag.TagSet((), lastTag) if firstOctet in self.__tagCache: self.__tagSetCache[firstOctet] = tagSet else: tagSet = lastTag + tagSet state = stDecodeLength debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'tag decoded into %s, decoding length' % tagSet) if state == stDecodeLength: # Decode length if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding') firstOctet = oct2int(substrate[0]) if firstOctet == 128: size = 1 length = -1 elif firstOctet < 128: length, size = firstOctet, 1 else: size = firstOctet & 0x7F # encoded in size bytes length = 0 lengthString = substrate[1:size + 1] # missing check on maximum size, which shouldn't be a # problem, we can handle more than is possible if len(lengthString) != size: raise error.SubstrateUnderrunError( '%s<%s at %s' % (size, len(lengthString), tagSet)) for char in lengthString: length = (length << 8) | oct2int(char) size += 1 substrate = substrate[size:] if length != -1 and len(substrate) < length: raise error.SubstrateUnderrunError( '%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 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 asn1Spec is None: state = stGetValueDecoderByTag else: state = stGetValueDecoderByAsn1Spec # # There're two ways of creating subtypes in ASN.1 what influences # decoder operation. These methods are: # 1) Either base types used in or no IMPLICIT tagging has been # applied on subtyping. # 2) Subtype syntax drops base type information (by means of # IMPLICIT tagging. # The first case allows for complete tag recovery from substrate # while the second one requires original ASN.1 type spec for # decoding. # # In either case a set of tags (tagSet) is coming from substrate # in an incremental, tag-by-tag fashion (this is the case of # EXPLICIT tag which is most basic). Outermost tag comes first # from the wire. # if state == stGetValueDecoderByTag: if tagSet in self.__tagMap: concreteDecoder = self.__tagMap[tagSet] else: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: _k = tagSet[:1] if _k in self.__tagMap: concreteDecoder = self.__tagMap[_k] else: concreteDecoder = None if concreteDecoder: state = stDecodeValue else: state = stTryAsExplicitTag if debug.logger and debug.logger & debug.flagDecoder: debug.logger( 'codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push( concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__) if state == stGetValueDecoderByAsn1Spec: if isinstance(asn1Spec, (dict, tagmap.TagMap)): if tagSet in asn1Spec: __chosenSpec = asn1Spec[tagSet] else: __chosenSpec = None if debug.logger and debug.logger & debug.flagDecoder: debug.logger('candidate ASN.1 spec is a map of:') for t, v in asn1Spec.getPosMap().items(): debug.logger(' %s -> %s' % (t, v.__class__.__name__)) if asn1Spec.getNegMap(): debug.logger('but neither of: ') for t, v in asn1Spec.getNegMap().items(): debug.logger(' %s -> %s' % (t, v.__class__.__name__)) debug.logger( 'new candidate ASN.1 spec is %s, chosen by %s' % (__chosenSpec is None and '<none>' or __chosenSpec.prettyPrintType(), tagSet)) else: __chosenSpec = asn1Spec debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) if __chosenSpec is not None and ( tagSet == __chosenSpec.getTagSet() or tagSet in __chosenSpec.getTagMap()): # use base type for codec lookup to recover untagged types baseTagSet = __chosenSpec.baseTagSet if __chosenSpec.typeId is not None and \ __chosenSpec.typeId in self.__typeMap: # ambiguous type concreteDecoder = self.__typeMap[__chosenSpec.typeId] debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'value decoder chosen for an ambiguous type by type ID %s' % (__chosenSpec.typeId, )) elif baseTagSet in self.__tagMap: # base type or tagged subtype concreteDecoder = self.__tagMap[baseTagSet] debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'value decoder chosen by base %s' % (baseTagSet, )) else: concreteDecoder = None if concreteDecoder: asn1Spec = __chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag else: concreteDecoder = None state = stTryAsExplicitTag if debug.logger and debug.logger & debug.flagDecoder: debug.logger( 'codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(__chosenSpec is None and '?' or __chosenSpec.__class__.__name__) if state == stTryAsExplicitTag: if tagSet and tagSet[0][1] == tag.tagFormatConstructed and \ tagSet[0][0] != tag.tagClassUniversal: # Assume explicit tagging concreteDecoder = explicitTagDecoder state = stDecodeValue else: concreteDecoder = None state = self.defaultErrorState debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure')) if state == stDumpRawValue: concreteDecoder = self.defaultRawDecoder debug.logger and debug.logger & debug.flagDecoder and debug.logger( 'codec %s chosen, decoding value' % concreteDecoder.__class__.__name__) state = stDecodeValue if state == stDecodeValue: if recursiveFlag == 0 and not substrateFun: # legacy def substrateFun(a, b, c): return a, b[:c] if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun) else: value, substrate = concreteDecoder.valueDecoder( fullSubstrate, substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun) state = stStop 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: raise error.PyAsn1Error('%s not in asn1Spec: %s' % (tagSet, asn1Spec)) if debug.logger and debug.logger & debug.flagDecoder: debug.scope.pop() debug.logger('decoder left scope %s, call completed' % debug.scope) return value, substrate
def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is not None: value = asn1Spec.clone(value) if value.isPlusInf: return (0x40,), False, False if value.isMinusInf: return (0x41,), False, False m, b, e = value if not m: return null, False, True if b == 10: if LOG: LOG('encoding REAL into character form') return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True elif b == 2: fo = 0x80 # binary encoding ms, m, encbase, e = self._chooseEncBase(value) if ms < 0: # mantissa sign fo |= 0x40 # sign bit # exponent & mantissa normalization if encbase == 2: while m & 0x1 == 0: 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 sf += 1 if sf > 3: raise error.PyAsn1Error('Scale factor overflow') # bug if raised fo |= sf << 2 eo = null if e == 0 or e == -1: eo = int2oct(e & 0xff) else: while e not in (0, -1): 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) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n & 0xff) + eo po = null while m: po = int2oct(m & 0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, False, True else: raise error.PyAsn1Error('Prohibited Real base %s' % b)