def verifyPacket(self, packet): plen = len(packet) # Check the number of sections if plen == self.MAX_SECTIONS: # Check the header if packet[self.SECTION_HEADER] == self.PROTOCOL_HEADER: # Check the version number (must be exact versions for now) if packet[self.SECTION_VERSION] == self.PROTOCOL_VERSION: # Check the checksum verify = packet[self.SECTION_SOURCE] + self.SECTION_SEPERATOR + packet[self.SECTION_VIA] + self.SECTION_SEPERATOR + packet[self.SECTION_DESTINATION] + self.SECTION_SEPERATOR + packet[self.SECTION_FLAGS] + self.SECTION_SEPERATOR + packet[self.SECTION_APPLICATION_ID] + self.SECTION_SEPERATOR + packet[self.SECTION_PACKET_ID] + self.SECTION_SEPERATOR + packet[self.SECTION_DATA] checksum = self.sha1(verify + self.SECTION_SEPERATOR + packet[self.SECTION_SIGNATURE]) # Convert the flags to old-style packet[self.SECTION_FLAGS] = bin(int(packet[self.SECTION_FLAGS], 16)).replace("0b", "").rjust(16, "0") if checksum == packet[self.SECTION_CHECKSUM]: # Application ID if self.REPEATER_MODE: # Set the application ID to the one we are verifying self.APPLICATION_ID = packet[self.SECTION_APPLICATION_ID] if packet[self.SECTION_APPLICATION_ID] == self.APPLICATION_ID: # Packet replay detection if not packet[self.SECTION_PACKET_ID] in self.prd: if self.DEBUG_MODE: self.log.info("Packet ID %s not present in PRD database, adding it in." % packet[self.SECTION_PACKET_ID]) self.prd[packet[self.SECTION_PACKET_ID]] = packet[self.SECTION_SOURCE] # Callsign signature if self.CRYPTO_AVAILABLE: if len(str(packet[self.SECTION_SIGNATURE]).replace("\x00", "")) > 0: client_key = os.path.join(self.CRYPTO_REMOTE_DIRECTORY, "%s.key" % self.sha1(packet[self.SECTION_SOURCE])) if os.path.exists(client_key): if self.DEBUG_MODE: self.log.info("Verifying the packet using the public key for %s..." % packet[self.SECTION_SOURCE]) test = DanRSA(client_key, None, None) result = test.verifyMessage(verify, self.decodeBase128ToStream(packet[self.SECTION_SIGNATURE], 0, True)) test = None if result: if self.DEBUG_MODE: self.log.info("The signature has validated using the public key for %s." % packet[self.SECTION_SOURCE]) else: if self.DEBUG_MODE: self.log.warn("The signature did NOT validate using the public key for %s." % packet[self.SECTION_SOURCE]) return result else: if self.DEBUG_MODE: self.log.warn("We do not have the public key for %s (%s.key), cannot verify the packet." % (packet[self.SECTION_SOURCE], self.sha1(packet[self.SECTION_SOURCE]))) if self.CRYPTO_ALLOW_UNSIGNED_PACKETS: return True else: if self.DEBUG_MODE: self.log.warn("Packet contained no signature.") if self.CRYPTO_ALLOW_UNSIGNED_PACKETS: return True else: if self.DEBUG_MODE: self.log.warn("Crypto isn't available so we can't validate the signature.") if self.CRYPTO_ALLOW_UNSIGNED_PACKETS: return True else: if self.DEBUG_MODE: self.log.warn("Packet replay detected by %s." % self.prd[packet[self.SECTION_PACKET_ID]]) else: if self.DEBUG_MODE: self.log.warn("The packet received application ID (%s) isn't for this application." % packet[self.SECTION_APPLICATION_ID]) else: if self.DEBUG_MODE: self.log.warn("Checksum mismatch (%s != %s)." % (checksum, packet[self.SECTION_CHECKSUM])) else: if self.DEBUG_MODE: self.log.warn("Version number mismatch (%s != %s)." % (self.PROTOCOL_VERSION, packet[self.SECTION_VERSION])) else: if self.DEBUG_MODE: self.log.warn("Invalid header (%s != %s)." % (self.PROTOCOL_HEADER, packet[self.SECTION_HEADER])) else: if self.DEBUG_MODE: self.log.warn("Wrong number of sections (%d != %d)." % (plen, self.MAX_SECTIONS)) return False
def splitPacket(self, packet): if self.DEBUG_MODE: self.log.info("Running...") plen = len(packet) if plen >= 80: # We need to validate the checksum here while we've got the raw packet checksum = bytearray() checksum.extend(packet[10:20]) # Source callsign checksum.extend(packet[20:30]) # Via checksum.extend(packet[30:40]) # Destination callsign checksum.extend(packet[40:42]) # Flags checksum.extend(packet[42:62]) # Application ID checksum.extend(packet[62:82]) # Packet ID checksum.extend(packet[82:plen - 26]) # Data (excluding the checksum of course) if self.encodeNumberToBase(int(self.sha1(str(checksum)), 16)).rjust(20, "\x00") == packet[plen - 26:plen - 6]: # OK, build a "old-style" list to keep compatibility ret = [] ret.append(packet[0:6]) # Header ret.append(packet[6:10]) # Version ret.append(packet[10:20].replace("\x00", "")) # Source callsign ret.append(packet[20:30].replace("\x00", "")) # Via ret.append(packet[30:40].replace("\x00", "")) # Destination callsign ret.append(bin(self.decodeBaseToNumber(packet[40:42])).replace("0b", "").rjust(16, "0")) # Flags ret.append(str(hex(self.decodeBaseToNumber(packet[42:62]))).replace("0x", "").replace("L", "")) # Application ID ret.append(str(hex(self.decodeBaseToNumber(packet[62:82]))).replace("0x", "").replace("L", "")) # Packet ID ret.append(packet[82:plen - 90]) # Data ret.append(packet[plen - 90:plen - 26]) # Signature ret.append(self.sha1(str(self.decodeBaseToNumber(packet[plen - 26:plen - 6])))) # Checksum ret.append(packet[plen - 6:plen]) # Footer if self.CRYPTO_AVAILABLE: # Check the callsign signature verify = bytearray() verify.extend(packet[10:20]) # Source callsign verify.extend(packet[20:30]) # Via verify.extend(packet[30:40]) # Destination callsign verify.extend(packet[40:42]) # Flags verify.extend(packet[42:62]) # Application ID verify.extend(packet[62:82]) # Packet ID verify.extend(packet[82:plen - 90]) # Data if len(str(ret[self.SECTION_SIGNATURE]).replace("\x00", "")) > 0: client_key = os.path.join(self.CRYPTO_REMOTE_DIRECTORY, "%s.key" % self.sha1(ret[self.SECTION_SOURCE])) if os.path.exists(client_key): if self.DEBUG_MODE: self.log.info("Verifying the packet using the public key for %s..." % ret[self.SECTION_SOURCE]) test = DanRSA(client_key, None, None) result = test.verifyMessage(str(verify), ret[self.SECTION_SIGNATURE]) test = None if result: if self.DEBUG_MODE: self.log.info("The signature has validated using the public key for %s." % ret[self.SECTION_SOURCE]) else: if self.DEBUG_MODE: self.log.warn("The signature did NOT validate using the public key for %s." % ret[self.SECTION_SOURCE]) return ret else: if self.DEBUG_MODE: self.log.warn("We do not have the public key for %s (%s.key), cannot verify the packet." % (ret[self.SECTION_SOURCE], self.sha1(ret[self.SECTION_SOURCE]))) if self.CRYPTO_ALLOW_UNSIGNED_PACKETS: return ret else: return None else: if self.DEBUG_MODE: self.log.warn("Packet contained no signature.") if self.CRYPTO_ALLOW_UNSIGNED_PACKETS: return ret else: return None else: if self.DEBUG_MODE: self.log.warn("Crypto isn't available so we can't validate the signature.") if self.CRYPTO_ALLOW_UNSIGNED_PACKETS: return ret else: return None else: if self.DEBUG_MODE: self.log.warn("Packet checksum mismatch.") return None else: if self.DEBUG_MODE: self.log.warn("Packet length mismatch (%d != %d)." % (plen, 68)) return None