def psubConstructedType(self, node, tp, fld, prim): # Iterate over field names, recursively retrieving quads; # add the field's offset to each of the quads, for its holding field compquads = [] for comp in node.components: if isinstance(comp, ExtensionMarker): continue subfld = tosym(comp.identifier) dprint('subfld is ', subfld) dprint('Generating PSUB node for %s', comp.type_decl.type_name) subquads = self.generate_psub_node(comp.type_decl, tp, subfld, prim) dprint('Generated PSUB node for %s', comp.type_decl.type_name) dprint('quads are %s', subquads) if fld == '0': subtp = tp else: subtp = tp + '_' + fld # TODO:TEST# subtp = tp + ('_' + fld if fld else '') # TODO:TEST# if subfld != '0': # TODO:TEST# if subfld: if subfld != '0': ofs = 'DER_OFFSET (' + tosym (self.unit) + ',' + subtp + ',' + subfld + ')' else: ofs = '0' for (idx, esz, pck, psb) in subquads: dprint('DEALING WITH', pck) if str(idx) == '0': idx = ofs else: idx = ofs + ' \\\n\t\t+ ' + str(idx) compquads.append((idx, esz, pck, psb)) dprint('psubConstructedType() RETURNS COMPONENT TRIPLES', compquads) return compquads
def psubConstructedType(self, node, tp, fld, prim): # Iterate over field names, recursively retrieving quads; # add the field's offset to each of the quads, for its holding field compquads = [] for comp in node.components: if isinstance(comp, ExtensionMarker): continue subfld = tosym(comp.identifier) dprint('subfld is ', subfld) dprint('Generating PSUB node for %s', comp.type_decl.type_name) subquads = self.generate_psub_node(comp.type_decl, tp, subfld, prim) dprint('Generated PSUB node for %s', comp.type_decl.type_name) dprint('quads are %s', subquads) if fld == '0': subtp = tp else: subtp = tp + '_' + fld # TODO:TEST# subtp = tp + ('_' + fld if fld else '') # TODO:TEST# if subfld != '0': # TODO:TEST# if subfld: if subfld != '0': ofs = 'DER_OFFSET (' + tosym( self.unit) + ',' + subtp + ',' + subfld + ')' else: ofs = '0' for (idx, esz, pck, psb) in subquads: dprint('DEALING WITH', pck) if str(idx) == '0': idx = ofs else: idx = ofs + ' \\\n\t\t+ ' + str(idx) compquads.append((idx, esz, pck, psb)) dprint('psubConstructedType() RETURNS COMPONENT TRIPLES', compquads) return compquads
def packSetType(self, node, implicit=False, outer_tag='DER_TAG_SET'): if not implicit: self.comma() self.write('DER_PACK_ENTER | ' + outer_tag) for comp in node.components: if isinstance(comp, ExtensionMarker): # TOOMUCH# self.comma() self.write('/* ...ASN.1 extensions... */') continue if isinstance( comp, ComponentType) and comp.components_of_type is not None: # Assuming COMPONENTS OF cannot be OPTIONAL, otherwise move this down self.comma() self.writeln('DER_PIMP_' + tosym(self.unit) + '_' + tosym(comp.components_of_type.type_name) + '\t/* COMPONENTS OF ' + str(comp.components_of_type) + ' */') continue if comp.optional or comp.default_value: self.comma() self.write('DER_PACK_OPTIONAL') if comp.type_decl is not None: # TODO: None would be due to components_of_type self.generate_pack_node(comp.type_decl, implicit=False) if not implicit: self.comma() self.write('DER_PACK_LEAVE')
def packTypeAssignment(self, node, tp, fld): # Issue each typedef b a only once, because -- even if you # use the same b, a each time -- type-redefinition is a C11 # feature, which isn't what we want. # self.to_be_overlaid is a list of (tname,tdecl) pairs to be created self.to_be_defined = [] self.to_be_overlaid = [(tosym(node.type_name), node.type_decl)] while len(self.to_be_overlaid) > 0: (tname, tdecl) = self.to_be_overlaid.pop(0) key = (self.unit, tname) if key not in self.issued_typedefs: self.issued_typedefs[key] = str(tdecl) self.writeln('KeehiveError') self.writeln('DER_PACK_{}('.format(tname)) self.writeln('){') #self.generate_pack_node(tdecl, tname, '0') self.writeln(')}') self.writeln() self.writeln('KeehiveError') self.writeln('DER_UNPACK_{}('.format(tname)) self.writeln('){') #self.generate_pack_node(tdecl, tname, '0') self.writeln(')}') self.writeln() else: if self.issued_typedefs[key] != str(tdecl): raise TypeError("Redefinition of type %s." % key[1]) for tbd in self.to_be_defined: if tbd != 'DER_OVLY_' + self.unit + '_' + tosym( node.type_name) + '_0': self.writeln('typedef struct ' + tbd + ' ' + tbd + ';') self.writeln()
def overlayConstructedType(self, node, tp, fld, naked=False): if not naked: if fld == '0': fld = '' else: fld = '_' + fld self.writeln('struct DER_OVLY_' + tosym (self.unit) + '_' + tp + fld + ' {') if fld: self.to_be_defined.append('DER_OVLY_' + tosym (self.unit) + '_' + tp + fld) for comp in node.components: if isinstance(comp, ExtensionMarker): self.writeln('\t/* ...ASN.1 extensions... */') continue if isinstance(comp, ComponentType) and comp.components_of_type is not None: self.writeln('\t/* COMPONENTS OF TYPE ' + str(comp.components_of_type) + ' */') self.writeln('//COMP :: ' + str(dir(comp))) self.writeln('//TYPE_DECL == ' + str(comp.type_decl)) self.writeln('//COMPONENTS_OF_TYPE :: ' + str(dir(comp.components_of_type))) self.writeln('//CHILDREN :: ' + str(dir(comp.components_of_type.children))) self.writeln('//TODO// Not sure how to get to elements and inline them here') # TODO:ARG1=???# self.overlayConstructedType (comp.components_of_type, naked=True) continue self.write('\t') subfld = tosym(comp.identifier) self.generate_overlay_node(comp.type_decl, tp, subfld) self.writeln(' ' + subfld + '; // ' + str(comp.type_decl)) if not naked: self.write('}')
def packTypeAssignment(self, node, tp, fld): # Issue each typedef b a only once, because -- even if you # use the same b, a each time -- type-redefinition is a C11 # feature, which isn't what we want. # self.to_be_overlaid is a list of (tname,tdecl) pairs to be created self.to_be_defined = [] self.to_be_overlaid = [(tosym(node.type_name), node.type_decl)] while len(self.to_be_overlaid) > 0: (tname, tdecl) = self.to_be_overlaid.pop(0) key = (self.unit, tname) if key not in self.issued_typedefs: self.issued_typedefs[key] = str(tdecl) self.writeln('KeehiveError') self.writeln('DER_PACK_{}('.format(tname)) self.writeln('){') #self.generate_pack_node(tdecl, tname, '0') self.writeln(')}') self.writeln() self.writeln('KeehiveError') self.writeln('DER_UNPACK_{}('.format(tname)) self.writeln('){') #self.generate_pack_node(tdecl, tname, '0') self.writeln(')}') self.writeln() else: if self.issued_typedefs[key] != str(tdecl): raise TypeError("Redefinition of type %s." % key[1]) for tbd in self.to_be_defined: if tbd != 'DER_OVLY_' + self.unit + '_' + tosym(node.type_name) + '_0': self.writeln('typedef struct ' + tbd + ' ' + tbd + ';') self.writeln()
def psubTypeAssignment(self, node, tp, fld, prim): # In lieu of typing context, fld is None; tp probably is too self.newcomma('; \\\n\t', '#define DEFINE_DER_PSUB_' + tosym (self.unit) + '_' + tosym(node.type_name) + ' \\\n\t') tp = tosym(node.type_name) subquads = self.generate_psub_node(node.type_decl, tp, '0', prim) dprint('SUBTRIPLES =', subquads) if subquads: self.generate_psub_sub(node.type_decl, subquads, tp, None) self.write(';\n\n') return []
def psubTypeAssignment(self, node, tp, fld, prim): # In lieu of typing context, fld is None; tp probably is too self.newcomma('; \\\n\t', '#define DEFINE_DER_PSUB_' + self.unit + '_' + tosym(node.type_name) + ' \\\n\t') tp = tosym(node.type_name) subquads = self.generate_psub_node(node.type_decl, tp, '0', prim) dprint('SUBTRIPLES =', subquads) if subquads: self.generate_psub_sub(node.type_decl, subquads, tp, None) self.write(';\n\n') return []
def packDefinedType(self, node, implicit=False, outer_tag=None): # There should never be anything of interest in outer_tag mod = node.module_ref or self.unit self.comma() if outer_tag is None: tagging = 'DER_PACK_' param = '' else: tagging = 'DER_PIMP_' param = '(' + outer_tag + ')' self.write(tagging + tosym(mod) + '_' + tosym(node.type_name) + param)
def packDefinedType(self, node, implicit=False, outer_tag=None): # There should never be anything of interest in outer_tag mod = node.module_ref or self.unit self.comma() if outer_tag is None: tagging = 'DER_PACK_' param = '' else: tagging = 'DER_PIMP_' param = '(' + outer_tag + ')' self.write(tagging + tosym(mod) + '_' + tosym(node.type_name) + param)
def packTypeAssignment(self, node, implicit=False): # TODO# Would be nicer to have DER_PACK_ backref to DER_PIMP_ self.write('#define DER_PIMP_' + tosym (self.unit) + '_' + tosym(node.type_name) + '(implicit_tag)') self.newcomma(', \\\n\t', ' \\\n\t') self.generate_pack_node(node.type_decl, implicit=False, outer_tag='implicit_tag') self.writeln() self.writeln() self.write('#define DER_PACK_' + tosym (self.unit) + '_' + tosym(node.type_name)) self.newcomma(', \\\n\t', ' \\\n\t') self.generate_pack_node(node.type_decl, implicit=False) self.writeln() self.writeln()
def packTypeAssignment(self, node, implicit=False): # TODO# Would be nicer to have DER_PACK_ backref to DER_PIMP_ self.write('#define DER_PIMP_' + self.unit + '_' + tosym(node.type_name) + '(implicit_tag)') self.newcomma(', \\\n\t', ' \\\n\t') self.generate_pack_node(node.type_decl, implicit=False, outer_tag='implicit_tag') self.writeln() self.writeln() self.write('#define DER_PACK_' + self.unit + '_' + tosym(node.type_name)) self.newcomma(', \\\n\t', ' \\\n\t') self.generate_pack_node(node.type_decl, implicit=False) self.writeln() self.writeln()
def pygen_class(clsnm, tp, ctxofs, pck, recp, numcrs): # TODO# Sometimes, ASN1Atom may have a specific supertp supertp = tosym(tp) self.writeln('class ' + clsnm + ' (' + supertp + '):') atom = type(recp) == int subatom = atom and tp != 'ASN1Atom' said_sth = False if tp not in ['ASN1SequenceOf', 'ASN1SetOf'] and not subatom: self.writeln(' _der_packer = ' + pymap_packer(pck)) said_sth = True if not atom: self.writeln(' _recipe = ' + pymap_recipe(recp, ctxofs)) said_sth = True if False: # TODO# Always fixed or computed self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True if not atom: self.writeln(' _context = globals ()') self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True elif subatom: self.writeln(' _context = ' + api_prefix + '.__dict__') if not said_sth: self.writeln(' pass') self.writeln()
def psubDefinedType(self, node, tp, fld, prim): dprint('DefinedType type:', node.type_name, '::', type(node.type_name)) modnm = node.module_ref dprint('AFTER modnm = node.module_ref', modnm) if not modnm and self.semamod.imports: syms = self.semamod.imports.imports dprint('SYMS.KEYS() =', syms.keys()) for mod in syms.keys(): if node.type_name in syms[mod]: modnm = str(mod).lower() dprint('AFTER modnm = str(mod).lower ()', modnm) break if modnm is None: # NOT_IN_GENERAL# modnm = node.module_ref modnm = self.unit.lower() dprint('AFTER modnm = self.unit.lower ()', modnm) dprint('MODNM =', modnm, '::', type(modnm)) dprint('Referenced module:', modnm, '::', type(modnm)) dprint('Searching case-insensitively in:', self.refmods.keys()) if modnm not in self.refmods: raise Exception('Module name "%s" not found' % modnm) thetype = self.refmods[modnm].user_types()[node.type_name] dprint('References:', thetype, '::', type(thetype)) popunit = self.unit popsema = self.semamod self.unit = modnm self.semamod = self.refmods[modnm] tp2 = tosym(node.type_name) fld2 = '0' subtuples = self.generate_psub_node(thetype, tp2, fld2, prim and (popunit == self.unit) and (tp == tp2)) self.semamod = popsema self.unit = popunit dprint('SUBTUPLES =', subtuples) return subtuples
def pymap_recipe(recp, ctxofs, ln='\n '): if type(recp) == int: retval = str(recp + ctxofs) elif recp[0] == '_NAMED': (_NAMED, map_) = recp ln += ' ' retval = "('_NAMED', {" comma = False for (fld, fldrcp) in map_.items(): if comma: retval += ',' + ln else: retval += ln retval += "'" + tosym(fld) + "': " retval += pymap_recipe(fldrcp, ctxofs, ln) comma = True retval += ' } )' elif recp[0] in ['_SEQOF', '_SETOF']: (_STHOF, allidx, pck, num, inner_recp) = recp ln += ' ' retval = "('" + _STHOF + "', " retval += str(allidx) + ', ' retval += pymap_packer(pck, ln) + ',' retval += str(num) + ',' + ln retval += pymap_recipe(inner_recp, 0, ln) + ' )' elif recp[0] == '_TYPTR': (_TYPTR, [clsnm], ofs) = recp retval = repr(recp) else: assert False, 'Unexpected recipe tag ' + str(recp[0]) # retval = repr(recp) return retval
def overlayConstructedType(self, node, tp, fld, naked=False): if not naked: if fld == '0': fld = '' else: fld = '_' + fld self.writeln('struct DER_OVLY_' + self.unit + '_' + tp + fld + ' {') if fld: self.to_be_defined.append('DER_OVLY_' + self.unit + '_' + tp + fld) for comp in node.components: if isinstance(comp, ExtensionMarker): self.writeln('\t/* ...ASN.1 extensions... */') continue if isinstance(comp, ComponentType) and comp.components_of_type is not None: self.writeln('\t/* COMPONENTS OF TYPE ' + str(comp.components_of_type) + ' */') self.writeln('//COMP :: ' + str(dir(comp))) self.writeln('//TYPE_DECL == ' + str(comp.type_decl)) self.writeln('//COMPONENTS_OF_TYPE :: ' + str(dir(comp.components_of_type))) self.writeln('//CHILDREN :: ' + str(dir(comp.components_of_type.children))) self.writeln('//TODO// Not sure how to get to elements and inline them here') # TODO:ARG1=???# self.overlayConstructedType (comp.components_of_type, naked=True) continue self.write('\t') subfld = tosym(comp.identifier) self.generate_overlay_node(comp.type_decl, tp, subfld) self.writeln(' ' + subfld + '; // ' + str(comp.type_decl)) if not naked: self.write('}')
def psubDefinedType(self, node, tp, fld, prim): dprint('DefinedType type:', node.type_name, '::', type(node.type_name)) modnm = node.module_ref dprint('AFTER modnm = node.module_ref', modnm) if not modnm and self.semamod.imports: syms = self.semamod.imports.imports dprint('SYMS.KEYS() =', syms.keys()) for mod in syms.keys(): if node.type_name in syms[mod]: modnm = str(mod).lower() dprint('AFTER modnm = str(mod).lower ()', modnm) break if modnm is None: # NOT_IN_GENERAL# modnm = node.module_ref modnm = self.unit.lower() dprint('AFTER modnm = self.unit.lower ()', modnm) dprint('MODNM =', modnm, '::', type(modnm)) dprint('Referenced module:', modnm, '::', type(modnm)) dprint('Searching case-insensitively in:', self.refmods.keys()) if modnm not in self.refmods: raise Exception('Module name "%s" not found' % modnm) thetype = self.refmods[modnm].user_types()[node.type_name] dprint('References:', thetype, '::', type(thetype)) popunit = self.unit popsema = self.semamod self.unit = modnm self.semamod = self.refmods[modnm] tp2 = tosym(node.type_name) fld2 = '0' subtuples = self.generate_psub_node(thetype, tp2, fld2, prim and (popunit == self.unit) and (tp == tp2)) self.semamod = popsema self.unit = popunit dprint('SUBTUPLES =', subtuples) return subtuples
def generate_tail(self): self.writeln() self.writeln() self.writeln('#endif /* QUICK_DER_' + tosym (self.unit) + '_H */') self.writeln() self.writeln() self.writeln('/* asn2quickder output for ' + self.semamod.name + ' ends here */')
def generate_head(self): self.writeln('#') self.writeln('# asn2quickder output for ' + self.semamod.name + ' -- automatically generated') self.writeln('#') self.writeln( '# Read more about Quick `n\' Easy DER on https://github.com/vanrein/quick-der' ) self.writeln('#') self.writeln() self.writeln() self.writeln('#') self.writeln('# Import general definitions and package dependencies') self.writeln('#') self.writeln() self.writeln('import quick_der.api as ' + api_prefix) self.writeln() if not self.semamod.imports: return imports = self.semamod.imports.imports for rm in imports.keys(): pymod = tosym(str(rm).rsplit('.', 1)[0]).lower() self.write('from ' + pymod + ' import ') self.writeln(', '.join(map(tosym, imports[rm]))) self.writeln() self.writeln()
def pygen_class(clsnm, tp, ctxofs, pck, recp, numcrs): # TODO# Sometimes, ASN1Atom may have a specific supertp supertp = tosym(tp) self.writeln('class ' + clsnm + ' (' + supertp + '):') atom = type(recp) == int subatom = atom and tp != 'ASN1Atom' said_sth = False if tp not in ['ASN1SequenceOf', 'ASN1SetOf'] and not subatom: self.writeln(' _der_packer = ' + pymap_packer(pck)) said_sth = True if not atom: self.writeln(' _recipe = ' + pymap_recipe(recp, ctxofs)) said_sth = True if False: # TODO# Always fixed or computed self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True if not atom: self.writeln(' _context = globals ()') self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True elif subatom: self.writeln(' _context = ' + api_prefix + '.__dict__') if not said_sth: self.writeln(' pass') self.writeln()
def pymap_recipe(recp, ctxofs, ln='\n '): if type(recp) == int: retval = str(recp + ctxofs) elif recp[0] == '_NAMED': (_NAMED, map_) = recp ln += ' ' retval = "('_NAMED', {" comma = False for (fld, fldrcp) in map_.items(): if comma: retval += ',' + ln else: retval += ln retval += "'" + tosym(fld) + "': " retval += pymap_recipe(fldrcp, ctxofs, ln) comma = True retval += ' } )' elif recp[0] in ['_SEQOF', '_SETOF']: (_STHOF, allidx, pck, num, inner_recp) = recp ln += ' ' retval = "('" + _STHOF + "', " retval += str(allidx) + ', ' retval += pymap_packer(pck, ln) + ',' retval += str(num) + ',' + ln retval += pymap_recipe(inner_recp, 0, ln) + ' )' elif recp[0] == '_TYPTR': (_TYPTR, [clsnm], ofs) = recp retval = repr(recp) else: assert False, 'Unexpected recipe tag ' + str(recp[0]) # retval = repr(recp) return retval
def generate_head(self): self.writeln('#') self.writeln('# asn2quickder output for ' + self.semamod.name + ' -- automatically generated') self.writeln('#') self.writeln('# Read more about Quick `n\' Easy DER on https://github.com/vanrein/quick-der') self.writeln('#') self.writeln() self.writeln() self.writeln('#') self.writeln('# Import general definitions and package dependencies') self.writeln('#') self.writeln() self.writeln('import quick_der.api as ' + api_prefix) self.writeln() if not self.semamod.imports: return imports = self.semamod.imports.imports for rm in imports.keys(): pymod = tosym(str(rm).rsplit('.', 1)[0]).lower() self.write('from ' + pymod + ' import ') self.writeln(', '.join(map(tosym, imports[rm]))) self.writeln() self.writeln()
def pygenValueAssignment(self, node): # We only found INTEGER and OBJECTIDENTIFIER in RFCs # Note that these forms are computed while loading, so not fast cls = tosym(node.type_decl) var = tosym(node.value_name) if cls == 'INTEGER': val = self.pyvalInteger(node.value) cls = api_prefix + '.ASN1Integer' elif cls == 'OBJECTIDENTIFIER': val = self.pyvalOID(node.value) cls = api_prefix + '.ASN1OID' else: val = 'UNDEF_MAP2DER("""' + str(node.value) + '""")' self.comment(str(node)) # Must provide a context for name resolution, even {} will do self.writeln(var + ' = ' + cls + ' (bindata=[' + val + '], context={})') self.writeln()
def generate_tail(self): self.writeln() self.writeln() self.writeln('#endif /* QUICK_DER_' + tosym(self.unit) + '_H */') self.writeln() self.writeln() self.writeln('/* asn2quickder output for ' + self.semamod.name + ' ends here */')
def pygenValueAssignment(self, node): # We only found INTEGER and OBJECTIDENTIFIER in RFCs # Note that these forms are computed while loading, so not fast cls = tosym(node.type_decl) var = tosym(node.value_name) if cls == 'INTEGER': val = self.pyvalInteger(node.value) cls = api_prefix + '.ASN1Integer' elif cls == 'OBJECTIDENTIFIER': val = self.pyvalOID(node.value) cls = api_prefix + '.ASN1OID' else: val = 'UNDEF_MAP2DER("""' + str(node.value) + '""")' self.comment(str(node)) # Must provide a context for name resolution, even {} will do self.writeln(var + ' = ' + cls + ' (bindata=[' + val + '], context={})') self.writeln()
def psubRepeatingStructureType(self, node, tp, fld, prim): elem_type = node.type_decl if isinstance(elem_type, NamedType): # We can ignore node.identifier... if fld == '0': # ...but in lieu of any name, why not, if it makes rfc4511 cool! fld = tosym(elem_type.identifier) elem_type = elem_type.type_decl if prim: # 1. produce derwalk for the nested field dprint('FIRST STEP OF psubRepeatingStructureType()') self.comma() self.write('const derwalk DER_PACK_' + tosym(self.unit) + '_' + tp + ('_' + fld if fld else '') + ' [] = {') surround_comma = self.getcomma() self.newcomma(', \\\n\t\t', ' \\\n\t\t') self.generate_pack_node(elem_type, implicit=False) self.comma() self.write('DER_PACK_END }') self.setcomma(*surround_comma) # 2. retrieve subquads for the nested field dprint('SECOND STEP OF psubRepeatingStructureType()') dprint('PROVIDED', tp) subquads = self.generate_psub_node(elem_type, tp, fld, False) # 3. produce triple structure definition for the nested field dprint('THIRD STEP OF psubRepeatingStructureType()') self.generate_psub_sub(node, subquads, tp, fld) else: pass # TODO:DEBUG# print 'FIRST,SECOND,THIRD STEP OF psubRepeatingStructureType() SKIPPED: SECONDARY' # 4. return a fresh triple structure defining this repeating field dprint('FOURTH STEP OF psubRepeatingStructureType()') nam = tosym(self.unit) + '_' + tp idx = '0' esz = 'DER_ELEMSZ (' + tosym( self.unit) + ',' + tp + ',' + (fld or '') + ')' if fld: fld = '_' + fld else: fld = '' pck = 'DER_PACK_' + nam + fld psb = 'DER_PSUB_' + nam + fld return [(idx, esz, pck, psb)]
def pyvalOID(self, valnode): retc = [] for oidcompo in valnode.components: if type(oidcompo) == NameForm: retc.append(api_prefix + '.der_parse_OID (' + tosym(oidcompo.name) + '.get())') elif type(oidcompo) == NumberForm: retc.append("'" + str(oidcompo.value) + "'") elif type(oidcompo) == NameAndNumberForm: retc.append("'" + str(oidcompo.number) + "'") retval = " + '.' + ".join(retc) retval = api_prefix + '.der_format_OID (' + retval.replace("' + '", '') + ')' return retval
def psubRepeatingStructureType(self, node, tp, fld, prim): elem_type = node.type_decl if isinstance(elem_type, NamedType): # We can ignore node.identifier... if fld == '0': # ...but in lieu of any name, why not, if it makes rfc4511 cool! fld = tosym(elem_type.identifier) elem_type = elem_type.type_decl if prim: # 1. produce derwalk for the nested field dprint('FIRST STEP OF psubRepeatingStructureType()') self.comma() self.write('const derwalk DER_PACK_' + tosym (self.unit) + '_' + tp + ('_' + fld if fld else '') + ' [] = {') surround_comma = self.getcomma() self.newcomma(', \\\n\t\t', ' \\\n\t\t') self.generate_pack_node(elem_type, implicit=False) self.comma() self.write('DER_PACK_END }') self.setcomma(*surround_comma) # 2. retrieve subquads for the nested field dprint('SECOND STEP OF psubRepeatingStructureType()') dprint('PROVIDED', tp) subquads = self.generate_psub_node(elem_type, tp, fld, False) # 3. produce triple structure definition for the nested field dprint('THIRD STEP OF psubRepeatingStructureType()') self.generate_psub_sub(node, subquads, tp, fld) else: pass # TODO:DEBUG# print 'FIRST,SECOND,THIRD STEP OF psubRepeatingStructureType() SKIPPED: SECONDARY' # 4. return a fresh triple structure defining this repeating field dprint('FOURTH STEP OF psubRepeatingStructureType()') nam = tosym (self.unit) + '_' + tp idx = '0' esz = 'DER_ELEMSZ (' + tosym (self.unit) + ',' + tp + ',' + (fld or '') + ')' if fld: fld = '_' + fld else: fld = '' pck = 'DER_PACK_' + nam + fld psb = 'DER_PSUB_' + nam + fld return [(idx, esz, pck, psb)]
def overlayRepeatingStructureType(self, node, tp, fld): # Generate a container element for the type... self.write('dernode') # ...and provoke overlay generation for DER_OVLY_mod_tp_fld elem_type = node.type_decl if isinstance(elem_type, NamedType): # We can ignore node.identifier... if fld == '0': # ...but in lieu of any name, why not, if it makes rfc4511 cool! fld = tosym(elem_type.identifier) elem_type = elem_type.type_decl # Create future work to describe the repeating elements' type self.to_be_overlaid.append((tp + '_' + fld, elem_type))
def overlayRepeatingStructureType(self, node, tp, fld): # Generate a container element for the type... self.write('dernode') # ...and provoke overlay generation for DER_OVLY_mod_tp_fld elem_type = node.type_decl if isinstance(elem_type, NamedType): # We can ignore node.identifier... if fld == '0': # ...but in lieu of any name, why not, if it makes rfc4511 cool! fld = tosym(elem_type.identifier) elem_type = elem_type.type_decl # Create future work to describe the repeating elements' type self.to_be_overlaid.append((tp + '_' + fld, elem_type))
def pyvalOID(self, valnode): retc = [] for oidcompo in valnode.components: if type(oidcompo) == NameForm: retc.append(api_prefix + '.der_parse_OID (' + tosym(oidcompo.name) + '.get())') elif type(oidcompo) == NumberForm: retc.append("'" + str(oidcompo.value) + "'") elif type(oidcompo) == NameAndNumberForm: retc.append("'" + str(oidcompo.number) + "'") retval = " + '.' + ".join(retc) retval = api_prefix + '.der_format_OID (' + retval.replace( "' + '", '') + ')' return retval
def packSetType(self, node, implicit=False, outer_tag='DER_TAG_SET'): if not implicit: self.comma() self.write('DER_PACK_ENTER | ' + outer_tag) for comp in node.components: if isinstance(comp, ExtensionMarker): # TOOMUCH# self.comma() self.write('/* ...ASN.1 extensions... */') continue if isinstance(comp, ComponentType) and comp.components_of_type is not None: # Assuming COMPONENTS OF cannot be OPTIONAL, otherwise move this down self.comma() self.writeln('DER_PIMP_' + tosym(self.unit) + '_' + tosym( comp.components_of_type.type_name) + '\t/* COMPONENTS OF ' + str(comp.components_of_type) + ' */') continue if comp.optional or comp.default_value: self.comma() self.write('DER_PACK_OPTIONAL') if comp.type_decl is not None: # TODO: None would be due to components_of_type self.generate_pack_node(comp.type_decl, implicit=False) if not implicit: self.comma() self.write('DER_PACK_LEAVE')
def generate_psub_sub(self, node, subquads, tp, fld): if fld is None: fld = '' else: fld = '_' + fld # OLD:TEST:TODO# mod = node.module_ref or self.unit mod = self.unit self.comma() self.writeln('const struct der_subparser_action DER_PSUB_' + tosym (mod) + '_' + tp + fld + ' [] = { \\') for (idx, esz, pck, sub) in subquads: self.writeln('\t\t{ ' + str(idx) + ', \\') self.writeln('\t\t ' + str(esz) + ', \\') self.writeln('\t\t ' + pck + ', \\') self.writeln('\t\t ' + sub + ' }, \\') self.writeln('\t\t{ 0, 0, NULL, NULL } \\') self.write('\t}')
def pyhelpConstructedType(self, node): pck = [] recp = {} for comp in node.components: if isinstance(comp, ExtensionMarker): # TODO# ...ASN.1 extensions... continue if isinstance(comp, ComponentType) and comp.components_of_type is not None: # TODO# ...COMPONENTS OF... continue (pck1, stru1) = self.generate_pytype(comp.type_decl) if isinstance(comp, ComponentType): if comp.optional or comp.default_value: pck1 = ['DER_PACK_OPTIONAL'] + pck1 pck = pck + pck1 recp[tosym(comp.identifier)] = stru1 return pck, ('_NAMED', recp)
def generate_psub_sub(self, node, subquads, tp, fld): if fld is None: fld = '' else: fld = '_' + fld # OLD:TEST:TODO# mod = node.module_ref or self.unit mod = self.unit self.comma() self.writeln('const struct der_subparser_action DER_PSUB_' + tosym(mod) + '_' + tp + fld + ' [] = { \\') for (idx, esz, pck, sub) in subquads: self.writeln('\t\t{ ' + str(idx) + ', \\') self.writeln('\t\t ' + str(esz) + ', \\') self.writeln('\t\t ' + pck + ', \\') self.writeln('\t\t ' + sub + ' }, \\') self.writeln('\t\t{ 0, 0, NULL, NULL } \\') self.write('\t}')
def pyhelpConstructedType(self, node): pck = [] recp = {} for comp in node.components: if isinstance(comp, ExtensionMarker): # TODO# ...ASN.1 extensions... continue if isinstance( comp, ComponentType) and comp.components_of_type is not None: # TODO# ...COMPONENTS OF... continue (pck1, stru1) = self.generate_pytype(comp.type_decl) if isinstance(comp, ComponentType): if comp.optional or comp.default_value: pck1 = ['DER_PACK_OPTIONAL'] + pck1 pck = pck + pck1 recp[tosym(comp.identifier)] = stru1 return pck, ('_NAMED', recp)
def overlayDefinedType(self, node, tp, fld): mod = node.module_ref or self.unit self.write('DER_OVLY_' + tosym(mod) + '_' + tosym(node.type_name))
def pygenTypeAssignment(self, node): def pymap_packer(pck, ln='\n '): retval = '(' + ln pck = pck + ['DER_PACK_END'] comma = '' for pcke in pck: pcke = pcke.replace('DER_', api_prefix + '.DER_') retval += comma + 'chr(' + pcke + ')' comma = ' +' + ln retval += ' )' return retval def pymap_recipe(recp, ctxofs, ln='\n '): if type(recp) == int: retval = str(recp + ctxofs) elif recp[0] == '_NAMED': (_NAMED, map_) = recp ln += ' ' retval = "('_NAMED', {" comma = False for (fld, fldrcp) in map_.items(): if comma: retval += ',' + ln else: retval += ln retval += "'" + tosym(fld) + "': " retval += pymap_recipe(fldrcp, ctxofs, ln) comma = True retval += ' } )' elif recp[0] in ['_SEQOF', '_SETOF']: (_STHOF, allidx, pck, num, inner_recp) = recp ln += ' ' retval = "('" + _STHOF + "', " retval += str(allidx) + ', ' retval += pymap_packer(pck, ln) + ',' retval += str(num) + ',' + ln retval += pymap_recipe(inner_recp, 0, ln) + ' )' elif recp[0] == '_TYPTR': (_TYPTR, [clsnm], ofs) = recp retval = repr(recp) else: assert False, 'Unexpected recipe tag ' + str(recp[0]) # retval = repr(recp) return retval def pygen_class(clsnm, tp, ctxofs, pck, recp, numcrs): # TODO# Sometimes, ASN1Atom may have a specific supertp supertp = tosym(tp) self.writeln('class ' + clsnm + ' (' + supertp + '):') atom = type(recp) == int subatom = atom and tp != 'ASN1Atom' said_sth = False if tp not in ['ASN1SequenceOf', 'ASN1SetOf'] and not subatom: self.writeln(' _der_packer = ' + pymap_packer(pck)) said_sth = True if not atom: self.writeln(' _recipe = ' + pymap_recipe(recp, ctxofs)) said_sth = True if False: # TODO# Always fixed or computed self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True if not atom: self.writeln(' _context = globals ()') self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True elif subatom: self.writeln(' _context = ' + api_prefix + '.__dict__') if not said_sth: self.writeln(' pass') self.writeln() # # body of pygenTypeAssignment # self.cursor_offset = 0 self.nested_typerefs = 0 self.nested_typecuts = 0 self.comment(str(node)) (pck, recp) = self.generate_pytype(node.type_decl) ofs = 0 tp = None if type(recp) == int: dertag = eval(pck[0], api.__dict__) if dertag in dertag2atomsubclass: tp = dertag2atomsubclass[dertag] else: tp = 'ASN1Atom' tp = api_prefix + '.' + tp elif recp[0] == '_NAMED': tp = api_prefix + '.ASN1ConstructedType' elif recp[0] == '_SEQOF': tp = api_prefix + '.ASN1SequenceOf' elif recp[0] == '_SETOF': tp = api_prefix + '.ASN1SetOf' elif recp[0] == '_TYPTR': (_TYPTR, [cls], ofs) = recp tp = str(cls) # TODO:GONE# if tp [:len(api_prefix)+1] == api_prefix + '.': # TODO:GONE# # Strip off api_prefix to avoid duplication # TODO:GONE# tp = tp [len(api_prefix)+1:] else: assert False, 'Unknown recipe tag ' + str(recp[0]) numcrs = self.cursor_offset pygen_class(tosym(node.type_name), tp, ofs, pck, recp, numcrs)
def pygenTypeAssignment(self, node): def pymap_packer(pck, ln='\n '): retval = '(' + ln pck = pck + ['DER_PACK_END'] comma = '' for pcke in pck: pcke = pcke.replace('DER_', api_prefix + '.DER_') retval += comma + 'chr(' + pcke + ')' comma = ' +' + ln retval += ' )' return retval def pymap_recipe(recp, ctxofs, ln='\n '): if type(recp) == int: retval = str(recp + ctxofs) elif recp[0] == '_NAMED': (_NAMED, map_) = recp ln += ' ' retval = "('_NAMED', {" comma = False for (fld, fldrcp) in map_.items(): if comma: retval += ',' + ln else: retval += ln retval += "'" + tosym(fld) + "': " retval += pymap_recipe(fldrcp, ctxofs, ln) comma = True retval += ' } )' elif recp[0] in ['_SEQOF', '_SETOF']: (_STHOF, allidx, pck, num, inner_recp) = recp ln += ' ' retval = "('" + _STHOF + "', " retval += str(allidx) + ', ' retval += pymap_packer(pck, ln) + ',' retval += str(num) + ',' + ln retval += pymap_recipe(inner_recp, 0, ln) + ' )' elif recp[0] == '_TYPTR': (_TYPTR, [clsnm], ofs) = recp retval = repr(recp) else: assert False, 'Unexpected recipe tag ' + str(recp[0]) # retval = repr(recp) return retval def pygen_class(clsnm, tp, ctxofs, pck, recp, numcrs): # TODO# Sometimes, ASN1Atom may have a specific supertp supertp = tosym(tp) self.writeln('class ' + clsnm + ' (' + supertp + '):') atom = type(recp) == int subatom = atom and tp != 'ASN1Atom' said_sth = False if tp not in ['ASN1SequenceOf', 'ASN1SetOf'] and not subatom: self.writeln(' _der_packer = ' + pymap_packer(pck)) said_sth = True if not atom: self.writeln(' _recipe = ' + pymap_recipe(recp, ctxofs)) said_sth = True if False: # TODO# Always fixed or computed self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True if not atom: self.writeln(' _context = globals ()') self.writeln(' _numcursori = ' + str(numcrs)) said_sth = True elif subatom: self.writeln(' _context = ' + api_prefix + '.__dict__') if not said_sth: self.writeln(' pass') self.writeln() # # body of pygenTypeAssignment # self.cursor_offset = 0 self.nested_typerefs = 0 self.nested_typecuts = 0 self.comment(str(node)) (pck, recp) = self.generate_pytype(node.type_decl) ofs = 0 tp = None if type(recp) == int: dertag = eval(pck[0], api.__dict__) if dertag in dertag2atomsubclass: tp = dertag2atomsubclass[dertag] else: tp = 'ASN1Atom' tp = api_prefix + '.' + tp elif recp[0] == '_NAMED': tp = api_prefix + '.ASN1ConstructedType' elif recp[0] == '_SEQOF': tp = api_prefix + '.ASN1SequenceOf' elif recp[0] == '_SETOF': tp = api_prefix + '.ASN1SetOf' elif recp[0] == '_TYPTR': (_TYPTR, [cls], ofs) = recp tp = str(cls) # TODO:GONE# if tp [:len(api_prefix)+1] == api_prefix + '.': # TODO:GONE# # Strip off api_prefix to avoid duplication # TODO:GONE# tp = tp [len(api_prefix)+1:] else: assert False, 'Unknown recipe tag ' + str(recp[0]) numcrs = self.cursor_offset pygen_class(tosym(node.type_name), tp, ofs, pck, recp, numcrs)
def generate_head(self): self.writeln('/*') self.writeln(' * asn2quickder output for ' + self.semamod.name + ' -- automatically generated') self.writeln(' *') self.writeln( ' * Read more about Quick `n\' Easy DER on https://github.com/vanrein/quick-der' ) self.writeln(' *') self.writeln(' */') self.writeln() self.writeln() self.writeln('#ifndef QUICK_DER_' + tosym(self.unit) + '_H') self.writeln('#define QUICK_DER_' + tosym(self.unit) + '_H') self.writeln() self.writeln() self.writeln('#include <arpa2/quick-der.h>') self.writeln() self.writeln() closer = '' rmfns = set() if not self.semamod.imports: return for rm in self.semamod.imports.imports.keys(): rmfns.add(str(rm).rsplit('.', 1)[0].lower()) for rmfn in rmfns: self.writeln('#include <quick-der/' + rmfn + '.h>') closer = '\n\n' self.write(closer) closer = '' for rm in self.semamod.imports.imports.keys(): rmfn = tosym(str(rm).rsplit('.', 1)[0]).lower() for sym in self.semamod.imports.imports[rm]: self.writeln('typedef DER_OVLY_' + tosym(rmfn) + '_' + tosym(sym) + ' DER_OVLY_' + tosym(self.unit) + '_' + tosym(sym) + ';') closer = '\n\n' self.write(closer) closer = '' for rm in self.semamod.imports.imports.keys(): rmfn = tosym(str(rm).rsplit('.', 1)[0]).lower() for sym in self.semamod.imports.imports[rm]: self.writeln('#define DER_PIMP_' + tosym(self.unit) + '_' + tosym(sym) + '(implicit_tag) DER_PIMP_' + tosym(rmfn) + '_' + tosym(sym) + '(implicit_tag)') self.writeln() self.writeln('#define DER_PACK_' + tosym(self.unit) + '_' + tosym(sym) + ' DER_PACK_' + tosym(rmfn) + '_' + tosym(sym) + '') closer = '\n\n' self.write(closer)
def overlayDefinedType(self, node, tp, fld): mod = node.module_ref or self.unit self.write('DER_OVLY_' + tosym(mod) + '_' + tosym(node.type_name))
def generate_head(self): self.writeln('/*') self.writeln(' * asn2quickder output for ' + self.semamod.name + ' -- automatically generated') self.writeln(' *') self.writeln(' * Read more about Quick `n\' Easy DER on https://github.com/vanrein/quick-der') self.writeln(' *') self.writeln(' */') self.writeln() self.writeln() self.writeln('#ifndef QUICK_DER_' + tosym (self.unit) + '_H') self.writeln('#define QUICK_DER_' + tosym (self.unit) + '_H') self.writeln() self.writeln() self.writeln('#include <arpa2/quick-der.h>') self.writeln() self.writeln() closer = '' rmfns = set() if not self.semamod.imports: return for rm in self.semamod.imports.imports.keys(): rmfns.add(tosym(str(rm).rsplit('.', 1)[0]).lower()) for rmfn in rmfns: self.writeln('#include <quick-der/' + rmfn + '.h>') closer = '\n\n' self.write(closer) closer = '' for rm in self.semamod.imports.imports.keys(): rmfn = tosym(str(rm).rsplit('.', 1)[0]).lower() for sym in self.semamod.imports.imports[rm]: self.writeln('typedef DER_OVLY_' + tosym(rmfn) + '_' + tosym(sym) + ' DER_OVLY_' + tosym( self.unit) + '_' + tosym(sym) + ';') closer = '\n\n' self.write(closer) closer = '' for rm in self.semamod.imports.imports.keys(): rmfn = tosym(str(rm).rsplit('.', 1)[0]).lower() for sym in self.semamod.imports.imports[rm]: self.writeln( '#define DER_PIMP_' + tosym(self.unit) + '_' + tosym(sym) + '(implicit_tag) DER_PIMP_' + tosym( rmfn) + '_' + tosym(sym) + '(implicit_tag)') self.writeln() self.writeln('#define DER_PACK_' + tosym(self.unit) + '_' + tosym(sym) + ' DER_PACK_' + tosym( rmfn) + '_' + tosym(sym) + '') closer = '\n\n' self.write(closer)