def handle_merge(self, filename): f = file(filename) contents = f.readlines() f.close() ver1 = [] ver2 = [] current = 'both' startv1 = '<<<<<<<' startboth = '>>>>>>>' startv2 = '=======' for line in contents: line = line.strip() if line.startswith(startv1): current = 'v1' continue elif line.startswith(startv2): current = 'v2' continue elif line.startswith(startboth): current = 'both' continue if current == 'both': ver1.append(line) ver2.append(line) elif current == 'v1': ver1.append(line) else: ver2.append(line) v1 = '\n'.join(ver1) v2 = '\n'.join(ver2) rec1 = self.parse_record(v1) rec2 = self.parse_record(v2) # check signatures if not any(crypto.check_signature(crypto.parse_pub_key(k.encode()), rec1[5], *rec1) for k in self.get_pubkeys(rec1[3])): raise NumbexDBError('invalid signature on %s'%rec1) if not any(crypto.check_signature(crypto.parse_pub_key(k.encode()), rec2[5], *rec2) for k in self.get_pubkeys(rec2[3])): raise NumbexDBError('invalid signature on %s'%rec2) # compare owners if rec1[3] != rec2[3]: raise NumbexDBError('cannot merge %s and %s - owners differ'%(rec1, rec2)) # choose the more recent version from operator import itemgetter merged = max(rec1, rec2, key=itemgetter(4)) mergedtxt = self.make_record(*merged) f = file(filename, 'wb') f.write(mergedtxt) f.close()
def test_csv_signature(self): v = ["+48581234", "+48581999", "sip.freeconet.pl", "freeconet", datetime.datetime.now()] v1 = crypto.make_csv_record(*v) s = crypto.sign_record(self.dsa, *v) self.assert_(crypto.check_signature(self.dsa, s, *v)) s1 = crypto.sign_csv_record(self.dsa, v1) self.assert_(crypto.check_csv_signature(self.dsa, s1, v1))
def check_record_signature(self, cur, start, end, sip, owner, mdate, sig): keys = self._get_pub_keys(cur, owner) for key in keys: dsapub = crypto.parse_pub_key(key.encode('ascii')) if crypto.check_signature(dsapub, sig, start, end, sip, owner, mdate): return True return False
def test_soap(self): port = self.port pemkeys = database.Database._example_privkeys extract_pubkey = lambda x: crypto.extract_pub_key( crypto.parse_priv_key(pemkeys[x])) keys = dict(freeconet=extract_pubkey('freeconet'), telarena=extract_pubkey('telarena')) basedatacsv = '''+481234,+481299,sip.freeconet.pl,freeconet,2009-01-03T23:59:30.123456 +4820000,+4820999,sip.freeconet.pl,freeconet,2009-01-03T23:59:30.123456 +4821000,+4821111,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456 +4830000,+4830099,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456''' basedata = utils.parse_csv_data(StringIO(basedatacsv)) tosend = '''+4821005,+4821011,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000 +481222,+481240,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000 +481298,+481301,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000 +4821113,+4821123,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000''' # no signatures self.assertRaises(ZSI.FaultException, send, StringIO(tosend), url=self.url) # test overwriting send_sign(StringIO(basedatacsv), StringIO(pemkeys['freeconet']), url=self.url) result = pull_all(url=self.url) parsed = utils.parse_csv_data(StringIO(result)) for rowe, rowr in zip(basedata, parsed): self.assertEqual(rowr[:-1], rowe) for row in parsed: key = crypto.parse_pub_key(keys[row[3]]) self.assert_(crypto.check_signature(key, row[5], *row)) # test updates send_sign(StringIO(tosend), StringIO(pemkeys['freeconet']), url=self.url) expected = utils.parse_csv_data(StringIO('''+481241,+481297,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456 +4821000,+4821004,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456 +4821012,+4821111,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456''')) result = pull_sign(url=self.url) parsed = utils.parse_csv_data(StringIO(result)) for rowe, rowr in zip(expected, parsed): self.assertEqual(rowe[:-1], rowr[:-2])
def import_data(self, data, delete=None): '''data format: iterator of records in format produced by parse_record''' self.log.info('importing %s records...', len(data)) tstart = time.time() keycache = {} for row in data: if len(row) != 6: self.log.warning("invalid record %s", row) return False owner = row[3] if not owner in keycache: pemkeys = [k.encode('ascii') if isinstance(k, unicode) else k for k in self.get_pubkeys(owner)] keycache[owner] = [crypto.parse_pub_key(k) for k in pemkeys] if not keycache[owner]: self.log.warning("no key found for %s", row) return False checked_data = row[:-1] sig = row[-1] if not any(crypto.check_signature(key, row[-1], *row[:-1]) for key in keycache[owner]): self.log.warning("invalid signature %s", row) return False else: self.log.debug("signature valid for %s", row) shelf = self.shelf if delete is not None: for k in delete: path = self.make_repo_path(k) del shelf[path] for r in data: start, end, sip, owner, mdate, rsasig = r num = self.make_repo_path(start) newrec = self.make_record(start, end, sip, owner, mdate, rsasig) self.log.debug("inserting %s", r) # 'key in shelf' doesn't seem to work try: oldrec = shelf[num] except KeyError: shelf[num] = newrec else: if oldrec != newrec: shelf[num] = newrec self.log.debug("syncing repository, this may take a while") self.sync() self.log.debug("checking for overlaps") overlaps = self.check_overlaps() if overlaps: self.log.warning("import resulted in overlapping ranges, rolling back") parents = shelf.get_parent_ids() if len(parents) == 0: # TODO clear it all pass elif len(parents) == 1: shelf.update_head(parents[0]) else: raise NumbexDBError("import commit with multiple parents?!?") shelf.git("gc", "--auto") self.reload() return False tend = time.time() self.log.info("import successful, time %.3f", tend-tstart) return True
def test_invalid_signature(self): v = ["+48581234", "+48581999", "sip.freeconet.pl", "freeconet", datetime.datetime.now()] self.assertFalse(crypto.check_signature(self.dsa, "this is an invalid signature", *v)) self.assertFalse(crypto.check_signature(self.dsa, "not base64!", *v))
def test_pubkey_signature(self): v = ["+48581234", "+48581999", "sip.freeconet.pl", "freeconet", datetime.datetime.now()] dsapub = crypto.parse_pub_key(self.pubkey) sig = crypto.sign_record(self.dsa, *v) self.assert_(crypto.check_signature(dsapub, sig, *v))
def test_basic_signature(self): v = ["+48581234", "+48581999", "sip.freeconet.pl", "freeconet", datetime.datetime.now()] sig = crypto.sign_record(self.dsa, *v) self.assert_(crypto.check_signature(self.dsa, sig, *v))