def _issue_revocations(self, revoked_ifs): """ Store a RevocationInfo in ZK and send a revocation to all BRs. :param list revoked_ifs: A list of interfaces that needs to be revoked. """ # Only the master BS issues revocations. if not self.zk.have_lock(): return # Process revoked interfaces. for if_id in revoked_ifs: rev_info = self._get_ht_proof(if_id) logging.info("Issuing revocation: %s", rev_info.short_desc()) if self._labels: REVOCATIONS_ISSUED.labels(**self._labels).inc() self._process_revocation(rev_info) border_metas = [] # Add all BRs. for br in self.topology.border_routers: br_addr, br_port = br.int_addrs[0].public[0] border_metas.append(UDPMetadata.from_values(host=br_addr, port=br_port)) # Add local path server. ps_meta = [] if self.topology.path_servers: try: addr, port = self.dns_query_topo(PATH_SERVICE)[0] except SCIONServiceLookupError: addr, port = None, None # Create a meta if there is a local path service if addr: ps_meta.append(UDPMetadata.from_values(host=addr, port=port)) self._send_ifstate_update(border_metas, ps_meta)
def _issue_revocations(self, revoked_ifs): """ Store a RevocationInfo in ZK and send a revocation to all BRs. :param list revoked_ifs: A list of interfaces that needs to be revoked. """ # Only the master BS issues revocations. if not self.zk.have_lock(): return # Process revoked interfaces. infos = [] for if_id in revoked_ifs: br = self.ifid2br[if_id] rev_info = RevocationInfo.from_values( self.addr.isd_as, if_id, br.interfaces[if_id].link_type, int(time.time()), self.REVOCATION_TTL) logging.info("Issuing revocation: %s", rev_info.short_desc()) if self._labels: REVOCATIONS_ISSUED.labels(**self._labels).inc() chain = self._get_my_cert() _, cert_ver = chain.get_leaf_isd_as_ver() src = DefaultSignSrc.from_values( rev_info.isd_as(), cert_ver, self._get_my_trc().version).pack() srev_info = SignedRevInfo.from_values(rev_info.copy().pack(), ProtoSignType.ED25519, src) srev_info.sign(self.signing_key) # Add to revocation cache self.if_revocations[if_id] = srev_info self._process_revocation(srev_info) infos.append(IFStateInfo.from_values(if_id, False, srev_info)) border_metas = [] # Add all BRs. for br in self.topology.border_routers: br_addr, br_port = br.int_addrs.public[0] border_metas.append( UDPMetadata.from_values(host=br_addr, port=br_port)) # Add local path server. ps_meta = [] if self.topology.path_servers: try: addr, port = self.dns_query_topo(ServiceType.PS)[0] except SCIONServiceLookupError: addr, port = None, None # Create a meta if there is a local path service if addr: ps_meta.append(UDPMetadata.from_values(host=addr, port=port)) self._send_ifstate_update(infos, border_metas, ps_meta)
def handle_ifid_packet(self, pld, meta): """ Update the interface state for the corresponding interface. :param pld: The IFIDPayload. :type pld: IFIDPayload """ ifid = pld.p.relayIF with self.ifid_state_lock: if ifid not in self.ifid_state: raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid) br = self.ifid2br[ifid] br.interfaces[ifid].to_if_id = pld.p.origIF prev_state = self.ifid_state[ifid].update() if prev_state == InterfaceState.INACTIVE: logging.info("IF %d activated", ifid) elif prev_state in [ InterfaceState.TIMED_OUT, InterfaceState.REVOKED ]: logging.info("IF %d came back up.", ifid) if not prev_state == InterfaceState.ACTIVE: if self.zk.have_lock(): # Inform BRs about the interface coming up. state_info = IFStateInfo.from_values( ifid, True, self._get_ht_proof(ifid)) pld = IFStatePayload.from_values([state_info]) for br in self.topology.border_routers: br_addr, br_port = br.int_addrs[0].public[0] meta = UDPMetadata.from_values(host=br_addr, port=br_port) self.send_meta(pld.copy(), meta, (br_addr, br_port))
def handle_ifid_packet(self, cpld, meta): """ Update the interface state for the corresponding interface. :param pld: The IFIDPayload. :type pld: IFIDPayload """ pld = cpld.union assert isinstance(pld, IFIDPayload), type(pld) ifid = meta.pkt.path.get_hof().ingress_if with self.ifid_state_lock: if ifid not in self.ifid_state: raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid) br = self.ifid2br[ifid] br.interfaces[ifid].to_if_id = pld.p.origIF prev_state = self.ifid_state[ifid].update() if prev_state == InterfaceState.INACTIVE: logging.info("IF %d activated.", ifid) elif prev_state in [ InterfaceState.TIMED_OUT, InterfaceState.REVOKED ]: logging.info("IF %d came back up.", ifid) if prev_state != InterfaceState.ACTIVE: if self.zk.have_lock(): # Inform BRs about the interface coming up. metas = [] for br in self.topology.border_routers: br_addr, br_port = br.ctrl_addrs.public metas.append( UDPMetadata.from_values(host=br_addr, port=br_port)) info = IFStateInfo.from_values(ifid, True) self._send_ifstate_update([info], metas)
def _get_msg_meta(self, packet, addr, sock): pkt = self._parse_packet(packet) if not pkt: logging.error("Cannot parse packet:\n%s" % packet) return None, None # Create metadata: rev_pkt = pkt.reversed_copy() if rev_pkt.l4_hdr.TYPE == L4Proto.UDP: meta = UDPMetadata.from_values(ia=rev_pkt.addrs.dst.isd_as, host=rev_pkt.addrs.dst.host, path=rev_pkt.path, ext_hdrs=rev_pkt.ext_hdrs, port=rev_pkt.l4_hdr.dst_port) elif rev_pkt.l4_hdr.TYPE == L4Proto.SCMP: meta = SCMPMetadata.from_values(ia=rev_pkt.addrs.dst.isd_as, host=rev_pkt.addrs.dst.host, path=rev_pkt.path, ext_hdrs=rev_pkt.ext_hdrs) else: logging.error("Cannot create meta for: %s" % pkt) return None, None # FIXME(PSz): for now it is needed by SIBRA service. meta.pkt = pkt try: pkt.parse_payload() except SCIONParseError: logging.error("Cannot parse payload of: %s" % pkt) return None, meta return pkt.get_payload(), meta
def _get_trc(self, isd_as, trc_ver): """ Get TRC from local storage or memory. :param ISD_AS isd_as: ISD-AS identifier. :param int trc_ver: TRC file version. """ trc = self.trust_store.get_trc(isd_as[0], trc_ver) if not trc: # Requesting TRC file from cert server trc_tuple = isd_as[0], trc_ver now = int(time.time()) if (trc_tuple not in self.trc_requests or (now - self.trc_requests[trc_tuple] > self.REQUESTS_TIMEOUT)): trc_req = TRCRequest.from_values(isd_as, trc_ver) logging.info("Requesting %sv%s TRC", isd_as[0], trc_ver) try: addr, port = self.dns_query_topo(CERTIFICATE_SERVICE)[0] except SCIONServiceLookupError as e: logging.warning("Sending TRC request failed: %s", e) return None meta = UDPMetadata.from_values(host=addr, port=port) self.send_meta(trc_req, meta) self.trc_requests[trc_tuple] = now return None return trc
def _build_meta(self, ia=None, host=None, path=None, port=0, reuse=False, one_hop=False): if ia is None: ia = self.addr.isd_as if path is None: path = SCIONPath() if not one_hop: return self._DefaultMeta.from_values(ia, host, path, port=port, reuse=reuse) # One hop path extension in handled in a different way in TCP and UDP if self._DefaultMeta == TCPMetadata: return TCPMetadata.from_values(ia, host, path, port=port, reuse=reuse, flags=TCPFlags.ONEHOPPATH) return UDPMetadata.from_values(ia, host, path, port=port, reuse=reuse, ext_hdrs=[OneHopPathExt()])
def _get_cs(self): """ Lookup certificate servers address and return meta. """ try: addr, port = self.dns_query_topo(CERTIFICATE_SERVICE)[0] except SCIONServiceLookupError as e: logging.warning("Lookup for certificate service failed: %s", e) return None return UDPMetadata.from_values(host=addr, port=port)
def _send_rev_to_local_ps(self, rev_info): """ Sends the given revocation to its local path server. :param rev_info: The RevocationInfo object :type rev_info: RevocationInfo """ if self.zk.have_lock() and self.topology.path_servers: try: addr, port = self.dns_query_topo(PATH_SERVICE)[0] except SCIONServiceLookupError: # If there are no local path servers, stop here. return meta = UDPMetadata.from_values(host=addr, port=port) self.send_meta(rev_info.copy(), meta)
def _mk_prop_pcb_meta(self, pcb, dst_ia, egress_if): ts = pcb.get_timestamp() asm = self._create_asm(pcb.p.ifID, egress_if, ts, pcb.last_hof()) if not asm: return None, None pcb.add_asm(asm) pcb.sign(self.signing_key) one_hop_path = self._create_one_hop_path(egress_if) if self.DefaultMeta == TCPMetadata: return pcb, self.DefaultMeta.from_values(ia=dst_ia, host=SVCType.BS_A, path=one_hop_path, flags=TCPFlags.ONEHOPPATH) return pcb, UDPMetadata.from_values(ia=dst_ia, host=SVCType.BS_A, path=one_hop_path, ext_hdrs=[OneHopPathExt()])
def _issue_revocation(self, if_id): """ Store a RevocationInfo in ZK and send a revocation to all BRs. :param if_id: The interface that needs to be revoked. :type if_id: int """ # Only the master BS issues revocations. if not self.zk.have_lock(): return rev_info = self._get_ht_proof(if_id) logging.error("Issuing revocation for IF %d.", if_id) # Issue revocation to all BRs. info = IFStateInfo.from_values(if_id, False, rev_info) pld = IFStatePayload.from_values([info]) for br in self.topology.get_all_border_routers(): meta = UDPMetadata.from_values(host=br.addr, port=br.port) self.send_meta(pld.copy(), meta, (br.addr, br.port)) self._process_revocation(rev_info) self._send_rev_to_local_ps(rev_info)
def _issue_revocation(self, if_id): """ Store a RevocationInfo in ZK and send a revocation to all BRs. :param if_id: The interface that needs to be revoked. :type if_id: int """ # Only the master BS issues revocations. if not self.zk.have_lock(): return rev_info = self._get_ht_proof(if_id) logging.info("Issuing revocation: %s", rev_info.short_desc()) if self._labels: REVOCATIONS_ISSUED.labels(**self._labels).inc() # Issue revocation to all BRs. info = IFStateInfo.from_values(if_id, False, rev_info) pld = IFStatePayload.from_values([info]) for br in self.topology.border_routers: br_addr, br_port = br.int_addrs[0].public[0] meta = UDPMetadata.from_values(host=br_addr, port=br_port) self.send_meta(pld.copy(), meta, (br_addr, br_port)) self._process_revocation(rev_info) self._send_rev_to_local_ps(rev_info)
def _get_msg_meta(self, packet, addr, sock): pkt = self._parse_packet(packet) if not pkt: logging.error("Cannot parse packet:\n%s" % packet) return None, None # Create metadata: rev_pkt = pkt.reversed_copy() # Skip OneHopPathExt (if exists) exts = [] for e in rev_pkt.ext_hdrs: if not isinstance(e, OneHopPathExt): exts.append(e) if rev_pkt.l4_hdr.TYPE == L4Proto.UDP: meta = UDPMetadata.from_values(ia=rev_pkt.addrs.dst.isd_as, host=rev_pkt.addrs.dst.host, path=rev_pkt.path, ext_hdrs=exts, port=rev_pkt.l4_hdr.dst_port) elif rev_pkt.l4_hdr.TYPE == L4Proto.SCMP: meta = SCMPMetadata.from_values(ia=rev_pkt.addrs.dst.isd_as, host=rev_pkt.addrs.dst.host, path=rev_pkt.path, ext_hdrs=exts) else: logging.error("Cannot create meta for: %s" % pkt) return None, None # FIXME(PSz): for now it is needed by SIBRA service. meta.pkt = pkt try: pkt.parse_payload() except SCIONParseError as e: logging.error("Cannot parse payload\n Error: %s\n Pkt: %s", e, pkt) return None, meta return pkt.get_payload(), meta