def __init__(self, face, onResult, onError, name, rrtype=dns.rdatatype.FH, parse_dns=True, verify=True, cache=None): self.face = face self.onResult = onResult self.onError = onError self.name = name self.rrtype = rrtype self.parse_dns = parse_dns self.verify = verify self.zone = ndn.Name() self.hint = None self.i = 0 self.label_real = ndn.Name() self.label_logical = ndn.Name() self.fh_result = None self.fh_msg = None self.cachingQuery = cache if self.cachingQuery is None: raise ("CachingQuery object is required")
def _onRequest(self, scope, zone, basename, interest): _LOG.debug(">> scope [%s], zone [%s], basename [%s], interest [%s]" % (scope, zone.name, basename, interest.name)) if self._enable_dyndns: if interest.name[-1] == "NDNUPDATE": self._dyndns._processDyNDNS(zone, basename, interest) return dataPacket = self._getRequestedData( zone, ndn.Name(basename[len(scope):]), ndn.Name(interest.name[len(scope):])) if dataPacket: if len(scope) == 0: self._face.put(dataPacket) else: # will sign with real key, but not sure if it is really necessary encapPacket = ndns.createSignedData( self._ndns, ndn.Name(scope).append(dataPacket.name), dataPacket.toWire(), dataPacket.signedInfo.freshnessSeconds, zone.default_key) _LOG.debug("Encapsulating into [%s]" % encapPacket.name) self._face.put(encapPacket) return
def _disableZone (self, zone): name = zone.name self._face.clearInterestFilter (ndn.Name (name).append ("DNS")) activeScopes = [] for scope in self._scopes + self._autoScope: if not scope.isPrefixOf (name): activeScopes.append (str (scope)) self._face.clearInterestFilter (ndn.Name (scope).append ("\xF0.").append (name).append ("DNS")) _LOG.info ('<< Stop serving zone [%s] (%s)' % (name, activeScopes))
def _enableZone (self, zone): name = zone.name self._face.setInterestFilter (ndn.Name (name).append ("DNS"), functools.partial (self._onRequest, ndn.Name (), zone)) activeScopes = [] for scope in self._scopes + self._autoScope: if not scope.isPrefixOf (name): activeScopes.append (str (scope)) self._face.setInterestFilter (ndn.Name (scope).append ("\xF0.").append (name).append ("DNS"), functools.partial (self._onRequest, ndn.Name (scope).append ("\xF0."), zone)) _LOG.info ('>> Start serving zone [%s] (%s)' % (name, activeScopes))
def _getRequestedData (self, zone, basename, interestName): _LOG.debug (">> REAL: basename [%s], interest [%s]" % (basename, interestName)) if str(interestName[-1])[0] == '\xFD': # allow version to be specified, but ignore it for the database lookup request_name = ndn.Name (interestName[:-1]) else: request_name = interestName try: label = dns.name.from_text (ndns.dnsify (str (ndn.Name (request_name[len(basename):-1])))).relativize (origin = dns.name.root) except Exception, e: _LOG.debug ("Invalid request: label [%s] cannot be dnsified (%s)" % (request_name[len(basename):-1], e)) return None
def expressQueryFor(self, face, onResult, onError, zone, hint, label, rrtype, parse_dns=True, limit_left=10, verify=True): # _LOG.debug ('expressQueryFor') if isinstance(rrtype, str): rrtype = dns.rdatatype.to_text(dns.rdatatype.from_text(rrtype)) else: rrtype = dns.rdatatype.to_text(rrtype) query = ndn.Name(zone).append("DNS") if len(label) > 0: query = query.append(label) query = query.append(rrtype) self.expressQueryForRaw(face, onResult, onError, query, zone, hint, label, rrtype, parse_dns, limit_left, verify)
def build_interest(self, latest): if self.start_with_latest: latest=True self.start_with_latest = False excl = ndn.ExclusionFilter() excl.add_any() excl.add_name(ndn.Name([self.latest_version])) # expected result should be between those two names excl.add_name(ndn.Name([self.last_version_marker])) excl.add_any() interest = ndn.Interest(name=self.base_name, exclude=excl, \ minSuffixComponents=3, maxSuffixComponents=3) interest.childSelector = 1 if latest else 0 return interest
def __init__(self, prefix, handle): self.prefix = ndn.Name(prefix) self.handle = handle self.content_objects = [] self.cleanup_time = 15 * 60 # keep responses for 15 min handle.setInterestFilter(self.prefix, self)
def __init__(self, data_dir, scopes=[], enable_dyndns=True): self.data_dir = data_dir self._scopes = [ndn.Name(scope) for scope in scopes] self._zones = [] self._autoScope = [] self._enable_dyndns = enable_dyndns
def _onNsResult(self, ns_result, ns_msg): ns_rrdata = random.choice(ns_msg.answer[0].items) # A couple of cheats, to handle names like "/ndn/ucla.edu/irl" # ns_target = ndnify (ns_rrdata.target.relativize (dns.name.root).to_text ()) dns_zone = dns.name.from_text(dnsify(str(self.zone))) dns_ns_target = ns_rrdata.target if dns_ns_target.is_subdomain(dns_zone): ns_label = ndn.Name( ndnify(dns_ns_target.relativize(dns_zone).to_text())) self.cachingQuery.expressQueryFor(self.face, self._onFhResult, self.onError, self.zone, self.hint, ns_label, dns.rdatatype.FH, parse_dns=True, verify=self.verify) else: # ns_target = ndn.Name (ndnify (dns_ns_target.relativize (dns.name.root).to_text ())) # IterativeQuery.expressQuery (self.face, self._onFhResult, self.onError, # ns_target, dns.rdatatype.FH, True) self.onError( "NS record pointing outside the domain structure is currently not supported" ) return
def upcall(self, kind, upcallInfo): if kind == ndn.UPCALL_FINAL: # any cleanup code here (so far I never had need for # this call type) return ndn.RESULT_OK if kind == ndn.UPCALL_INTEREST_TIMED_OUT: print("Got timeout!") return ndn.RESULT_OK # make sure we're getting sane responses if not kind in [ndn.UPCALL_CONTENT, ndn.UPCALL_CONTENT_UNVERIFIED, ndn.UPCALL_CONTENT_BAD]: print("Received invalid kind type: %d" % kind) sys.exit(100) matched_comps = upcallInfo.matchedComps response_name = upcallInfo.ContentObject.name org_prefix = response_name[:matched_comps] assert(org_prefix == self.root) if matched_comps == len(response_name): comp = ndn.Name([upcallInfo.ContentObject.digest()]) disp_name = ndn.Name(response_name) else: comp = response_name[matched_comps:matched_comps + 1] disp_name = response_name[:matched_comps + 1] if kind == ndn.UPCALL_CONTENT_BAD: print("*** VERIFICATION FAILURE *** %s" % response_name) print("%s [%s]" % (disp_name, \ "verified" if kind == ndn.UPCALL_CONTENT else "unverified")) self.exclusions.add_name(comp) self.express_my_interest() # explore next level if matched_comps + 1 < len(response_name): new = Slurp(response_name[:matched_comps + 1], self.handle) new.express_my_interest() return ndn.RESULT_OK
def _authorizeKey(self, zone, basename, keyName, seqno): if (keyName[-1] != "NDNCERT"): return False key_label = dns.name.from_text (ndns.dnsify (str (ndn.Name (keyName[len(basename):-1])))).\ relativize (origin = dns.name.root) key = self.session.query(ndns.RRSet).with_parent(zone).filter_by( label=key_label.to_text(), rtype=dns.rdatatype.NDNCERT).first() if not key: _LOG.warn( "Key [%s] has been validated, but does not belong to the zone. Denying update" % keyName) return False current_key_seq = self.session.query( ndns.RRSet).with_parent(zone).filter_by( label=key_label.to_text(), rtype=dns.rdatatype.NDNCERTSEQ).first() if not current_key_seq: current_key_seq = ndns.RRSet(label=key_label.to_text(), zone=zone, rclass=dns.rdataclass.IN, rtype=dns.rdatatype.NDNCERTSEQ) rd = dns.rdtypes.IN.NDNCERTSEQ.NDNCERTSEQ( rdclass=dns.rdataclass.IN, rdtype=dns.rdatatype.NDNCERTSEQ, seq=ndn.Name()) rr = ndns.RR(ttl=0, rrdata=rd, rrset=current_key_seq) if current_key_seq.rrs[0].dns_rrdata.seq >= seqno: _LOG.warn( "Replay attack detected, denying the update with sequence number [%s]" % seqno) return False updated_rr = current_key_seq.rrs[0].dns_rrdata updated_rr.seq = seqno current_key_seq.rrs[0].rrdata = updated_rr current_key_seq.refresh_ndndata(self.session, zone.default_key) self.session.commit() return True
def _onFhResult(self, fh_result, fh_msg): if len(fh_msg.answer ) == 0 or fh_msg.answer[0].rdtype != dns.rdatatype.FH: self.onError( "Query returned a data packet, but records in answer section (should not really happen)" ) return self.fh_result = fh_result self.fh_msg = fh_msg fh_rrdata = random.choice(fh_msg.answer[0].items) self.hint = fh_rrdata.hint self.zone = self.zone.append(self.label_real) self.label_real = ndn.Name() self.label_logical = ndn.Name() # next iteration or check for the result self._getMostSpecificNsAnswer(tryEmptyLabel=False)
def expressQueryForRaw (face, onResult, onError, query, zone = None, hint = None, label = None, rrtype = None, parse_dns = True, limit_left = 10, verify = True): """ This is the most basic type of querying. The user has to explicity specify the authority zone, forwarding hint, label, and resource record type1 If ``zone``, ``label``, or ``rrtype`` are omitted or None, then they will be guessed from the query :param face: Face object :type face: ndn.Face :param onResult: Callback called when query returns a valid result: .. method:: onResult (data, dnsMessage) :param data: Data packet :type data: ndn.Data :param dnsMessage: if ``parse_dns`` flag is True, then fully parsed DNS message. if flag is False, then None :type dnsMessage: dns.Message :param onError: Callback called when query fails .. method:: onError (errorMessage) :param errorMessage: Error message with explanation of the error :type errorMessage: str :param query: NDN name of the query in form of ``<authority_zone>/DNS/<label(s)>/<RR-TYPE>`` :type query: ndn.Name :param zone: :param hint: :param label: :param rrtype: RR type to query, e.g., "NS" or "FH" (default: infer from the query) :type rrtype: str :param parse_dns: Flag whether to parse DNS message or not (default True) :type parse_dns: bool """ _LOG.debug ("expressQueryForRaw: query: %s, hint: %s" % (query, hint)) if hint and not hint.isPrefixOf (query): query = ndn.Name (hint).append ("\xF0.").append (query) else: hint = None state = SimpleQuery (face, onResult, onError, query, zone, hint, label, rrtype, parse_dns, limit_left, verify) face.expressInterest (query, state._onData, state._onTimeout)
def __init__(self, base_name, callback, handle=None, version=None, latest=True): handle = handle or ndn.Face() # some constants self.version_marker = '\xfd' self.first_version_marker = self.version_marker self.last_version_marker = '\xfe\x00\x00\x00\x00\x00\x00' self.base_name = ndn.Name(base_name) self.callback = callback self.handle = handle self.latest_version = version or self.first_version_marker self.start_with_latest = latest
def _getMostSpecificNsAnswer(self, tryEmptyLabel=False): _LOG.debug('_getMostSpecificNsAnswer [in %s for %s NS]' % (self.zone, self.label_logical)) if self.i < len(self.name): if not tryEmptyLabel: component = self.name[self.i] self.i += 1 self.label_logical = ndn.Name().append(ndnify(str(component))) self.label_real = ndn.Name().append(component) self.cachingQuery.expressQueryFor(self.face, self._onMostSpecificNsAnswer, self.onError, self.zone, self.hint, self.label_logical, dns.rdatatype.NS, parse_dns=True, verify=self.verify) else: self._onNoMoreNsDelegation()
def __init__(self, prefix, callback): self.gui_callback = callback self.friendly_names = {} self.handle = ndn.Face() self.chat_uri = ndn.Name(prefix) self.members_uri = self.chat_uri + "members" self.net_pull = VersionedPull(self.chat_uri, None, handle=self.handle) self.default_key = self.handle.getDefaultKey() digest = fix_digest(self.default_key.publicKeyID) self.friendly_names[digest] = getpass.getuser()
def get_certificate(): name = request.args.get('name') ndn_name = ndn.Name(str(name)) cert = mongo.db.certs.find_one({'name': str(name)}) if cert == None: abort(404) response = make_response(cert['cert']) response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Content-Disposition'] = 'attachment; filename=%s.ndncert' % str( ndn_name[-3]) return response
def get_operator_for_email(email): # very basic pre-validation user, domain = email.split('@', 2) operator = mongo.db.operators.find_one({'site_emails': {'$in': [domain]}}) if (operator == None): operator = mongo.db.operators.find_one( {'site_emails': { '$in': ['guest'] }}) if (operator == None): raise Exception("Unknown site for domain [%s]" % domain) # Special handling for guests ndn_domain = ndn.Name("/ndn/guest") assigned_namespace = \ ndn.Name('/ndn/guest') \ .append(email) else: if domain == "operators.named-data.net": ndn_domain = ndn.Name(str(user)) assigned_namespace = ndn.Name(str(user)) else: ndn_domain = ndnify(domain) assigned_namespace = \ ndn.Name('/ndn') \ .append(ndn_domain) \ .append(user) # return various things return { 'operator': operator, 'user': user, 'domain': domain, 'ndn_domain': ndn_domain, 'assigned_namespace': assigned_namespace }
def __init__(self, prefix, nick=getpass.getuser()): self.handle = ndn.Face() self.flow = FlowController(prefix, self.handle) #XXX: temporary, until we allow fetching key from key storage self.key = self.handle.getDefaultKey() self.keylocator = ndn.KeyLocator(self.key) self.prefix = ndn.Name(prefix) self.members_uri = self.prefix + "members" member_name = self.members_uri.appendKeyID( fix_digest(self.key.publicKeyID)) self.member_message = self.publish(member_name, nick) self.flow.put(self.member_message)
def ndn_label(self): """ Get label of the key name Note that this method makes sense only for ZSKs :returns: Key name minus the zone name :rtype: :py:class:`ndn.Name` """ name = self.name if name[:len(self.zone.name)] == self.zone.name: return ndn.Name(name[len(self.zone.name) + 1:-1]) else: raise KeyException( "Key does not belong to the zone (KSK should be stored in the parent zone!)" )
def _getRequestedData(self, zone, basename, interestName): _LOG.debug(">> REAL: basename [%s], interest [%s]" % (basename, interestName)) if str(interestName[-1])[0] == '\xFD': # allow version to be specified, but ignore it for the database lookup request_name = ndn.Name(interestName[:-1]) else: request_name = interestName try: rrtype = dns.rdatatype.from_text(str(request_name[-1])) except Exception, e: _LOG.debug( "Invalid request: unknown or unrecognized RR type [%s] (%s)" % (request_name[-1], e)) return None
def label(self): """ Get DNS label of the key name Note that this method makes sense only for ZSKs. For KSKs, use :py:attr:`parent_label`. :returns: DNS formatted string of key name minus the zone name :rtype: str """ name = self.name if name[:len(self.zone.name)] == self.zone.name: return dnsify(str(ndn.Name(name[len(self.zone.name) + 1:-1]))) else: raise KeyException( "Key does not belong to the zone (KSK should be stored in the parent zone!)" )
def main(args): if len(sys.argv) != 2: usage() name = ndn.Name(sys.argv[1]) data = ndnb_enumerate(generate_names()) key = ndn.Face.getDefaultKey() name = name.append('\xc1.E.be').appendKeyID(key).appendVersion() wrapper = Wrapper(name, key) sgmtr = segmenter(data, wrapper) handle = ndn.Face() for seg in sgmtr: handle.put(seg) return 0
def publish(name, content): key = ndn.Face.getDefaultKey() keylocator = ndn.KeyLocator(key) # Name co_name = ndn.Name(name).appendSegment(0) # SignedInfo si = ndn.SignedInfo() si.type = ndn.CONTENT_DATA si.finalBlockID = ndn.Name.num2seg(0) si.publisherPublicKeyDigest = key.publicKeyID si.keyLocator = keylocator # ContentObject co = ndn.ContentObject() co.content = content co.name = co_name co.signedInfo = si co.sign(key) return co
def parent_label(self): """ Get DNS label of the key, seen from the parent zone Note that this method makes sense only KSKs. For ZSKs use :py:attr:`label`. :returns: DNS formatted string of key name minus the parent's zone name :rtype: str """ if self.key_type != "KSK": raise KeyException( "Key.parent_label makes sense only for KSK keys") if self.parent_zone is None: raise KeyException( "Parent zone is not set (key is stored outside NDNS)") name = self.name if name[:len(self.parent_zone)] == self.parent_zone: return dnsify(str(ndn.Name(name[len(self.parent_zone) + 1:-1]))) else: raise KeyException("Key does not belong to the parent zone")
def get_candidates(): keyLocator = request.form['keyLocator'] timestamp = request.form['timestamp'] signature = request.form['signature'] query = \ ndn.Name('/cert-requests/get') \ .append(keyLocator) \ .append(timestamp) \ .append(base64.b64decode(signature)) operator = mongo.db.operators.find_one({'site_prefix': keyLocator}) if operator == None: abort(403) # do verification requests = mongo.db.requests.find({'operator_id': str(operator['_id'])}) output = [] for req in requests: output.append(req) # return json.dumps (output) return json.dumps(output, default=json_util.default)
def verifyAsync(self, face, dataPacket, onVerify, limit_left=10): """ onVerify: callback <void, dataPacket, status> """ if limit_left <= 0: onVerify(dataPacket, False) return if len(self.anchors) == 0: onVerify(dataPacket, False) return if not face: face = ndn.Face() face.defer_verification(True) data_name = dataPacket.name key_name = dataPacket.signedInfo.keyLocator.keyName try: [key_data, ttl] = self.trustedCache[str(data_name)] if time.time() > ttl: del self.trustedCache[str(data_name)] raise KeyError() onVerify(dataPacket, True) return except KeyError: pass _LOG.debug("%s data [%s] signed by [%s]" % ('--' * (11 - limit_left), data_name, key_name)) anchor = self.authorize_by_anchor(data_name, key_name) if anchor: verified = dataPacket.verify_signature(anchor) if verified: _LOG.info("%s anchor OKs [%s] (**[%s]**)" % ('--' * (11 - limit_left), data_name, key_name)) else: _LOG.info("%s anchor FAILs [%s]" % ('--' * (11 - limit_left), data_name)) onVerify(dataPacket, verified) return if not self.authorize_by_rule(data_name, key_name): onVerify(dataPacket, False) return try: [key, ttl] = self.trustedCache[str(key_name)] if time.time() > ttl: del self.trustedCache[str(key_name)] raise KeyError() _LOG.info("%s Using cached trusted version of key [%s]" % ('--' * (11 - limit_left), key_name)) onVerify(dataPacket, dataPacket.verify_signature(key)) return except KeyError: zone = ndn.Name() for comp in key_name: if comp == "DNS": break zone = zone.append(comp) nextLevelProcessor = NextLevelProcessor(face, self, dataPacket, onVerify, limit_left, key_name) if comp != "DNS": face.expressInterest(key_name, nextLevelProcessor.onData, nextLevelProcessor.onTimeout) elif len(zone) == 0: self.cachingQuery.expressQueryForRaw( face, nextLevelProcessor.onKeyData, nextLevelProcessor.onError, key_name, hint=None, parse_dns=False, limit_left=limit_left - 1) #, verify = False) else: self.cachingQuery.expressQueryForZoneFh( face, nextLevelProcessor.onHintData, nextLevelProcessor.onError, zone, verify=True)
def generate_names(): names = ["/Hello", "/World", "/This", "/is", "/an", "/enumeration", "/example"] return map(lambda x: ndn.Name(x), names)
def extract_cert_name(name): # remove two last components and remove "KEY" keyword at any position return ndn.Name( [component for component in name[:-2] if str(component) != 'KEY'])