def encodeLength(self, length, defMode): if not defMode and self.supportIndefLenMode: return (0x80,) if length < 0x80: return length, else: substrate = () while length: substrate = (length & 0xff,) + substrate length >>= 8 substrateLen = len(substrate) if substrateLen > 126: raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen) return (0x80 | substrateLen,) + substrate
def __init__(self, *args, **kwargs): self.__names = {} self.__numbers = {} anonymousNames = [] for namedValue in args: if isinstance(namedValue, (tuple, list)): try: name, number = namedValue except ValueError: raise error.PyAsn1Error('Not a proper attribute-value pair %r' % (namedValue,)) else: anonymousNames.append(namedValue) continue if name in self.__names: raise error.PyAsn1Error('Duplicate name %s' % (name,)) if number in self.__numbers: raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) self.__names[name] = number self.__numbers[number] = name for name, number in kwargs.items(): if name in self.__names: raise error.PyAsn1Error('Duplicate name %s' % (name,)) if number in self.__numbers: raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) self.__names[name] = number self.__numbers[number] = name if anonymousNames: number = self.__numbers and max(self.__numbers) + 1 or 0 for name in anonymousNames: if name in self.__names: raise error.PyAsn1Error('Duplicate name %s' % (name,)) self.__names[name] = number self.__numbers[number] = name number += 1
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] asn1Object = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(asn1Object, substrate, length) namedTypes = asn1Object.componentType if not self.orderedComponents or not namedTypes or namedTypes.hasOptionalOrDefault: seenIndices = set() idx = 0 while head: asn1Spec = self._getComponentTagMap(asn1Object, idx) component, head = decodeFun(head, asn1Spec) idx = self._getComponentPositionByType( asn1Object, component.effectiveTagSet, idx ) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) seenIndices.add(idx) idx += 1 if namedTypes and not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) else: for idx, asn1Spec in enumerate(namedTypes.values()): component, head = decodeFun(head, asn1Spec) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) if not namedTypes: asn1Object.verifySizeSpec() return asn1Object, tail
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): r = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(r, substrate, length) if r.getTagSet() == tagSet: # explicitly tagged Choice component, substrate = decodeFun(substrate, r.getComponentTagMap()) eooMarker, substrate = decodeFun(substrate) # eat up EOO marker if not eoo.endOfOctets.isSameTypeWith(eooMarker) or \ eooMarker != eoo.endOfOctets: raise error.PyAsn1Error('No EOO seen before substrate ends') else: component, substrate = decodeFun(substrate, r.getComponentTagMap(), tagSet, length, state) if isinstance(component, univ.Choice): effectiveTagSet = component.getEffectiveTagSet() else: effectiveTagSet = component.getTagSet() r.setComponentByType(effectiveTagSet, component, 0, asn1Spec is None) return r, substrate
def fromBinaryString(self, value): bitNo = 8 byte = 0 r = () for v in value: if bitNo: bitNo = bitNo - 1 else: bitNo = 7 r = r + (byte, ) byte = 0 if v == '0': v = 0 elif v == '1': v = 1 else: raise error.PyAsn1Error( 'Non-binary OCTET STRING initializer %s' % (v, )) byte = byte | (v << bitNo) return octets.ints2octs(r + (byte, ))
def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is None: component = value.getComponent() else: names = [ namedType.name for namedType in asn1Spec.componentType.namedTypes if namedType.name in value ] if len(names) != 1: raise error.PyAsn1Error( '%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', value)) name = names[0] component = value[name] asn1Spec = asn1Spec[name] return encodeFun(component, asn1Spec, **options), True, True
def setComponentByPosition(self, idx, value=None): l = len(self._componentValues) if idx >= l: self._componentValues = self._componentValues + (idx - l + 1) * [None] if value is None: if self._componentValues[idx] is None: self._componentValues[ idx] = self._componentType.getTypeByPosition(idx).clone() return self elif type(value) != types.InstanceType: t = self._componentType.getTypeByPosition(idx) if isinstance(t, base.AbstractSimpleAsn1Item): value = t.clone(value=value) else: raise error.PyAsn1Error('Instance value required') if self._componentType: self._verifyComponent(idx, value) self._verifySubtypeSpec(value, idx) self._componentValues[idx] = value return self
def __call__(self, value, **options): if debug.logger & debug.flagEncoder: logger = debug.logger else: logger = None if logger: logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), value.prettyPrintType(), value.prettyPrint())) if self.fixedDefLengthMode is not None: options.update(defMode=self.fixedDefLengthMode) if self.fixedChunkSize is not None: options.update(maxChunkSize=self.fixedChunkSize) tagSet = value.tagSet try: concreteEncoder = self.__typeMap[value.typeId] except KeyError: # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) try: concreteEncoder = self.__tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('No encoder for %s' % (value,)) if logger: logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet)) substrate = concreteEncoder.encode(value, self, **options) if logger: logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate))) return substrate
def getPositionByName(self, name): """Return field position by filed name. Parameters ---------- name: :py:class:`str` Field name Returns ------- : :py:class:`int` Field position in fields set Raises ------ : :class:`~pyasn1.error.PyAsn1Error` If *name* is not present or not unique within callee *NamedTypes* """ try: return self.__nameToPosMap[name] except KeyError: raise error.PyAsn1Error('Name %s not found' % (name, ))
def getNameByPosition(self, idx): """Return field name by its position in fields set. Parameters ---------- idx: :py:class:`idx` Field index Returns ------- : :py:class:`str` Field name Raises ------ : :class:`~pyasn1.error.PyAsn1Error` If given field name is not present in callee *NamedTypes* """ try: return self.__namedTypes[idx].name except IndexError: raise error.PyAsn1Error('Type position out of range')
def getPositionByType(self, tagSet): """Return field position by its ASN.1 type. Parameters ---------- tagSet: :class:`~pysnmp.type.tag.TagSet` ASN.1 tag set distinguishing one ASN.1 type from others. Returns ------- : :py:class:`int` ASN.1 type position in fields set Raises ------ : :class:`~pyasn1.error.PyAsn1Error` If *tagSet* is not present or ASN.1 types are not unique within callee *NamedTypes* """ try: return self.__tagToPosMap[tagSet] except KeyError: raise error.PyAsn1Error('Type %s not found' % (tagSet, ))
def getTypeByPosition(self, idx): """Return ASN.1 type object by its position in fields set. Parameters ---------- idx: :py:class:`int` Field index Returns ------- : ASN.1 type Raises ------ : :class:`~pyasn1.error.PyAsn1Error` If given position is out of fields range """ try: return self.__namedTypes[idx].asn1Object except IndexError: raise error.PyAsn1Error('Type position out of range')
def tagExplicitly(self, superTag): """Return explicitly tagged *TagSet* Create a new *TagSet* representing callee *TagSet* explicitly tagged with passed tag(s). With explicit tagging mode, new tags are appended to existing tag(s). Parameters ---------- superTag: :class:`~pyasn1.type.tag.Tag` *Tag* object to tag this *TagSet* Returns ------- : :class:`~pyasn1.type.tag.TagSet` New *TagSet* object """ if superTag.tagClass == tagClassUniversal: raise error.PyAsn1Error("Can't tag with UNIVERSAL class tag") if superTag.tagFormat != tagFormatConstructed: superTag = Tag(superTag.tagClass, tagFormatConstructed, superTag.tagId) return self + superTag
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): asn1Object = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(asn1Object, substrate, length) if asn1Object.tagSet == tagSet: # explicitly tagged Choice component, substrate = decodeFun(substrate, asn1Object.componentType.tagMapUnique) # eat up EOO marker eooMarker, substrate = decodeFun(substrate, allowEoo=True) if eooMarker is not eoo.endOfOctets: raise error.PyAsn1Error('No EOO seen before substrate ends') else: component, substrate = decodeFun( substrate, asn1Object.componentType.tagMapUnique, tagSet, length, state ) effectiveTagSet = component.effectiveTagSet asn1Object.setComponentByType( effectiveTagSet, component, verifyConstraints=False, matchTags=False, matchConstraints=False, innerFlag=False ) return asn1Object, substrate
def __computeTagMaps(self, unique): presentTypes = {} skipTypes = {} defaultType = None for namedType in self.__namedTypes: tagMap = namedType.asn1Object.tagMap if isinstance(tagMap, NamedTypes.PostponedError): return tagMap for tagSet in tagMap: if unique and tagSet in presentTypes: return NamedTypes.PostponedError( 'Non-unique tagSet %s of %s at %s' % (tagSet, namedType, self)) presentTypes[tagSet] = namedType.asn1Object skipTypes.update(tagMap.skipTypes) if defaultType is None: defaultType = tagMap.defaultType elif tagMap.defaultType is not None: raise error.PyAsn1Error('Duplicate default ASN.1 type at %s' % (self, )) return tagmap.TagMap(presentTypes, skipTypes, defaultType)
def plug(self, *args, **kw): raise error.PyAsn1Error( 'Uninitialized ASN.1 value ("%s" attribute looked up)' % name)
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 asDateTime(self): """Create :py:class:`datetime.datetime` object from a |ASN.1| object. Returns ------- : new instance of :py:class:`datetime.datetime` object """ text = str(self) if text.endswith('Z'): tzinfo = TimeMixIn.UTC text = text[:-1] elif '-' in text or '+' in text: if '+' in text: text, plusminus, tz = text.partition('+') else: text, plusminus, tz = text.partition('-') if self._shortTZ and len(tz) == 2: tz += '00' if len(tz) != 4: raise error.PyAsn1Error('malformed time zone offset %s' % tz) try: minutes = int(tz[:2]) * 60 + int(tz[2:]) if plusminus == '-': minutes *= -1 except ValueError: raise error.PyAsn1Error('unknown time specification %s' % self) tzinfo = TimeMixIn.FixedOffset(minutes, '?') else: tzinfo = None if '.' in text or ',' in text: if '.' in text: text, _, ms = text.partition('.') else: text, _, ms = text.partition(',') try: ms = int(ms) * 1000 except ValueError: raise error.PyAsn1Error( 'bad sub-second time specification %s' % self) else: ms = 0 if self._optionalMinutes and len(text) - self._yearsDigits == 6: text += '0000' elif len(text) - self._yearsDigits == 8: text += '00' try: dt = datetime.datetime.strptime( text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') except ValueError: raise error.PyAsn1Error('malformed datetime format %s' % self) return dt.replace(microsecond=ms, tzinfo=tzinfo)
def encode(self, value, asn1Spec=None, encodeFun=None, **options): if asn1Spec is None: tagSet = value.tagSet else: tagSet = asn1Spec.tagSet # untagged item? if not tagSet: substrate, isConstructed, isOctets = self.encodeValue( value, asn1Spec, encodeFun, **options) return substrate defMode = options.get('defMode', True) substrate = null for idx, singleTag in enumerate(tagSet.superTags): defModeOverride = defMode # base tag? if not idx: try: substrate, isConstructed, isOctets = self.encodeValue( value, asn1Spec, encodeFun, **options) except error.PyAsn1Error: exc = sys.exc_info() raise error.PyAsn1Error('Error encoding %r: %s' % (value, exc[1])) if LOG: LOG('encoded %svalue %s into %s' % (isConstructed and 'constructed ' or '', value, substrate)) if not substrate and isConstructed and options.get( 'ifNotEmpty', False): return substrate if not isConstructed: defModeOverride = True if LOG: LOG('overridden encoding mode into definitive for primitive type' ) header = self.encodeTag(singleTag, isConstructed) if LOG: LOG('encoded %stag %s into %s' % (isConstructed and 'constructed ' or '', singleTag, debug.hexdump(ints2octs(header)))) header += self.encodeLength(len(substrate), defModeOverride) if LOG: LOG('encoded %s octets (tag + payload) into %s' % (len(substrate), debug.hexdump(ints2octs(header)))) if isOctets: substrate = ints2octs(header) + substrate if not defModeOverride: substrate += self.eooOctetsSubstrate else: substrate = header + substrate if not defModeOverride: substrate += self.eooIntegerSubstrate if not isOctets: substrate = ints2octs(substrate) return substrate
def encodeValue(self, value, asn1Spec, encodeFun, **options): raise error.PyAsn1Error('Not implemented')
def __getattr__(self, attr): if attr in self.skipMethods: raise AttributeError('attribute %s not present' % attr) raise error.PyAsn1Error('No value for "%s"' % attr)
def encodeValue(self, value, asn1Spec, encodeFun, **options): substrate = null omitEmptyOptionals = options.get('omitEmptyOptionals', self.omitEmptyOptionals) if LOG: LOG('%sencoding empty OPTIONAL components' % (omitEmptyOptionals and 'not ' or '')) if asn1Spec is None: # instance of ASN.1 schema inconsistency = value.isInconsistent if inconsistency: raise inconsistency namedTypes = value.componentType for idx, component in enumerate(value.values()): if namedTypes: namedType = namedTypes[idx] if namedType.isOptional and not component.isValue: if LOG: LOG('not encoding OPTIONAL component %r' % (namedType, )) continue if namedType.isDefaulted and component == namedType.asn1Object: if LOG: LOG('not encoding DEFAULT component %r' % (namedType, )) continue if omitEmptyOptionals: options.update(ifNotEmpty=namedType.isOptional) # wrap open type blob if needed if namedTypes and namedType.openType: wrapType = namedType.asn1Object if wrapType.typeId in (univ.SetOf.typeId, univ.SequenceOf.typeId): substrate += encodeFun( component, asn1Spec, **dict(options, wrapType=wrapType.componentType)) else: chunk = encodeFun(component, asn1Spec, **options) if wrapType.isSameTypeWith(component): substrate += chunk else: substrate += encodeFun(chunk, wrapType, **options) if LOG: LOG('wrapped with wrap type %r' % (wrapType, )) else: substrate += encodeFun(component, asn1Spec, **options) else: # bare Python value + ASN.1 schema for idx, namedType in enumerate(asn1Spec.componentType.namedTypes): try: component = value[namedType.name] except KeyError: raise error.PyAsn1Error( 'Component name "%s" not found in %r' % (namedType.name, value)) if namedType.isOptional and namedType.name not in value: if LOG: LOG('not encoding OPTIONAL component %r' % (namedType, )) continue if namedType.isDefaulted and component == namedType.asn1Object: if LOG: LOG('not encoding DEFAULT component %r' % (namedType, )) continue if omitEmptyOptionals: options.update(ifNotEmpty=namedType.isOptional) componentSpec = namedType.asn1Object # wrap open type blob if needed if namedType.openType: if componentSpec.typeId in (univ.SetOf.typeId, univ.SequenceOf.typeId): substrate += encodeFun( component, componentSpec, **dict(options, wrapType=componentSpec.componentType)) else: chunk = encodeFun(component, componentSpec, **options) if componentSpec.isSameTypeWith(component): substrate += chunk else: substrate += encodeFun(chunk, componentSpec, **options) if LOG: LOG('wrapped with wrap type %r' % (componentSpec, )) else: substrate += encodeFun(component, componentSpec, **options) return substrate, True, True
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 __call__(self, value, asn1Spec=None, **options): try: if asn1Spec is None: typeId = value.typeId else: typeId = asn1Spec.typeId except AttributeError: raise error.PyAsn1Error('Value %r is not ASN.1 type instance ' 'and "asn1Spec" not given' % (value, )) if debug.logger & debug.flagEncoder: logger = debug.logger else: logger = None if logger: logger('encoder called in %sdef mode, chunk size %s for ' 'type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value)) if self.fixedDefLengthMode is not None: options.update(defMode=self.fixedDefLengthMode) if self.fixedChunkSize is not None: options.update(maxChunkSize=self.fixedChunkSize) try: concreteEncoder = self.__typeMap[typeId] if logger: logger('using value codec %s chosen by type ID %s' % (concreteEncoder.__class__.__name__, typeId)) except KeyError: if asn1Spec is None: tagSet = value.tagSet else: tagSet = asn1Spec.tagSet # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag) try: concreteEncoder = self.__tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet)) if logger: logger('using value codec %s chosen by tagSet %s' % (concreteEncoder.__class__.__name__, tagSet)) substrate = concreteEncoder.encode(value, asn1Spec, self, **options) if logger: logger( 'codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate))) return substrate
def encodeValue(self, value, asn1Spec, encodeFun, **options): substrate = null if asn1Spec is None: # instance of ASN.1 schema value.verifySizeSpec() namedTypes = value.componentType for idx, component in enumerate(value.values()): if namedTypes: namedType = namedTypes[idx] if namedType.isOptional and not component.isValue: continue if namedType.isDefaulted and component == namedType.asn1Object: continue if self.omitEmptyOptionals: options.update(ifNotEmpty=namedType.isOptional) chunk = encodeFun(component, asn1Spec, **options) # wrap open type blob if needed if namedTypes and namedType.openType: wrapType = namedType.asn1Object if wrapType.tagSet and not wrapType.isSameTypeWith( component): chunk = encodeFun(chunk, wrapType, **options) substrate += chunk else: # bare Python value + ASN.1 schema for idx, namedType in enumerate(asn1Spec.componentType.namedTypes): try: component = value[namedType.name] except KeyError: raise error.PyAsn1Error( 'Component name "%s" not found in %r' % (namedType.name, value)) if namedType.isOptional and namedType.name not in value: continue if namedType.isDefaulted and component == namedType.asn1Object: continue if self.omitEmptyOptionals: options.update(ifNotEmpty=namedType.isOptional) chunk = encodeFun(component, asn1Spec[idx], **options) # wrap open type blob if needed if namedType.openType: wrapType = namedType.asn1Object if wrapType.tagSet and not wrapType.isSameTypeWith( component): chunk = encodeFun(chunk, wrapType, **options) substrate += chunk return substrate, True, True
def setComponentByPosition(self, idx, value, verifyConstraints=True): raise error.PyAsn1Error('Method not implemented')
def getComponentByPosition(self, idx): raise error.PyAsn1Error('Method not implemented')
def __getattr__(self, attr): raise error.PyAsn1Error('No value for %s()' % attr)
def componentTagMap(self): raise error.PyAsn1Error('Method not implemented')
def __getitem__(self, i): raise error.PyAsn1Error('No value')