Esempio n. 1
0
	def handleInitiate(torId, displayName):
		'''We have requested contact with another id, so we can set up
		this new contact's name with a status of "requested"'''
		# TODO: If row already exists then get status (and name/displayname) and error with it
		# Add new row in db with id, name and "requested"
		if torId and torId != DbClient.getOwnTorId():
			DbClient.updateContact(torId, {'displayName':displayName, 'name':displayName,
			  'status':'requested'})
Esempio n. 2
0
	def testSharedContacts(self):
		# Delete whole profiles table
		DbClient._getProfileTable().remove({})
		self.assertEqual(DbClient._getProfileTable().count(), 0, "Profiles table should be empty")
		# Add own profile
		myTorId = "ABC123DEF456GH78"
		myprofile = {"name" : "Constantin Taylor", "keyid" : "someKeyId", "displayName" : "Me",
					"status" : "self", "ownprofile" : True}
		DbClient.updateContact(myTorId, myprofile)
		# Add friend who doesn't list any contacts
		person1TorId = "DEF123GHI456JK78"
		person1profile = {"name" : "Jeremy Flintstone", "keyid" : "someKeyId", "displayName" : "Uncle Jez",
					"status" : "trusted"}
		DbClient.updateContact(person1TorId, person1profile)
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertFalse(shared, "person1 shouldn't have any shared contacts")
		self.assertFalse(possIdsForThem, "person1 shouldn't have any possible contacts")
		self.assertFalse(possIdsForMe, "I shouldn't have any possible contacts")
		# Add second friend who lists first one as contact
		person2TorId = "GHI123JKL456MN78"
		person2profile = {"name" : "Karen Millhouse", "keyid" : "someKeyId", "displayName" : "Mum",
					"status" : "trusted", "contactlist":"DEF123GHI456JK78Jeremy,ABC123DEF456GH78Constantin,"}
		DbClient.updateContact(person2TorId, person2profile)
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertEqual(len(shared), 1, "person1 should have exactly one shared contact now")
		self.assertTrue(person2TorId in shared, "person1 should have p2 as shared contact now")
		self.assertFalse(possIdsForThem, "person1 shouldn't have any possible contacts")
		self.assertFalse(possIdsForMe, "I shouldn't have any possible contacts from p1")
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person2TorId)
		self.assertEqual(len(shared), 1, "person2 should have exactly one shared contact now")
		self.assertTrue(person1TorId in shared, "person2 should have p1 as shared contact now")
		self.assertFalse(possIdsForThem, "person2 shouldn't have any possible contacts")
		self.assertFalse(possIdsForMe, "I shouldn't have any possible contacts from p2")
		# Person 2 gets a new friend
		DbClient.updateContact(person2TorId, {"contactlist":"DEF123GHI456JK78Jeremy,ABC123DEF456GH78Constantin,MNO123PQR456ST78Scarlet Pimpernel"})
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertEqual(len(shared), 1, "person1 should still have one shared contact")
		self.assertTrue(person2TorId in shared, "person1 should have p2 as shared contact")
		self.assertFalse(possIdsForThem, "person1 shouldn't have any possible contacts")
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person2TorId)
		self.assertEqual(len(shared), 1, "person2 should still have one shared contact")
		self.assertTrue(person1TorId in shared, "person2 should have p1 as shared contact")
		self.assertFalse(possIdsForThem, "person2 shouldn't have any possible contacts")
		# We now make friends with MNO
		person3TorId = "MNO123PQR456ST78"
		person3profile = {"name" : "Scarlet Pimpernel", "keyid" : "someKeyId", "displayName" : "Stranger",
					"status" : "trusted"}
		DbClient.updateContact(person3TorId, person3profile)
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertEqual(len(shared), 1, "person1 should still have one shared contact")
		self.assertTrue(person2TorId in shared, "person1 should have p2 as shared contact")
		self.assertEqual(len(possIdsForThem), 1, "person1 should have one possible contact now")
		self.assertTrue(person3TorId in possIdsForThem, "person1 should have p3 as possible contact")
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person2TorId)
		self.assertEqual(len(shared), 2, "person2 should now have 2 shared contacts")
		self.assertTrue(person1TorId in shared, "person2 should have p1 as shared contact")
		self.assertTrue(person3TorId in shared, "person2 should have p3 as shared contact")
		self.assertFalse(possIdsForThem, "person2 shouldn't have any possible contacts")
Esempio n. 3
0
	def keyFingerprintChecked(torId):
		'''The fingerprint of this contact's public key has been checked (over a separate channel)'''
		# Check that userid exists and that status is currently "untrusted" (trusted also doesn't hurt)
		profile = DbClient.getProfile(torId, False)
		if profile and profile.get("status", "nostatus") in ["untrusted", "trusted"]:
			# Update the user's status to trusted
			DbClient.updateContact(torId, {"status" : "trusted"})
			# Trigger a StatusNotify to tell them we're online
			notify = StatusNotifyMessage(online=True, ping=True, profileHash=None)
			notify.recipients = [torId]
			DbClient.addMessageToOutbox(notify)
Esempio n. 4
0
	def checkAllContactsKeys():
		for c in DbClient.getMessageableContacts():
			torId = c.get("torid", None) if c else None
			if torId:
				keyId = c.get("keyid", None)
				if not keyId:
					print("No keyid found for torid", torId)
				elif not CryptoClient.getPublicKey(keyId):
					print("CryptoClient hasn't got a public key for torid", torId)
				if not keyId or not CryptoClient.getPublicKey(keyId):
					# We haven't got their key in our keyring!
					DbClient.updateContact(torId, {"status":"requested"})
Esempio n. 5
0
	def finish(self):
		'''Finished the key gen'''
		# Store key, name in mongo under own profile
		selectedKey = self.privateKeys[self.keypairListWidget.currentRow()]
		ownid = TorClient.getOwnId()
		# See if a name was entered before, if so use that
		myname = self.keygenParamBoxes['name'].text()
		if not myname:
			# Extract the name from the string which comes back from the key as "'Some Name (no comment) <*****@*****.**>'"
			myname = self.extractName(selectedKey['uids'])
		profile = {"name" : myname, "keyid" : selectedKey['keyid'], "torid" : ownid, "status" : "self", "ownprofile" : True}
		DbClient.updateContact(ownid, profile)
		return True
Esempio n. 6
0
	def testProfileHash(self):
		# Clear out and reset own profile
		myTorId = "ABC123DEF456GH78"
		myprofile = {"name" : "Constantin Taylor", "keyid" : "someKeyId", "displayName" : "Me",
					"status" : "self", "ownprofile" : True, "description":"Some fairly descriptive text",
					"birthday":None, "interests":"chocolate pudding with fudge"}
		DbClient.updateContact(myTorId, myprofile)
		firstHash = DbClient.calculateHash(DbClient.getProfile())
		self.assertEqual(firstHash, "12ae5c8dc8e1c2186b4ed4918040bb16", "First hash not what I was expecting")
		# Now change interests and check that hash changes
		DbClient.updateContact(myTorId, {"interests":"roasted vegetables and hummus"})
		secondHash = DbClient.calculateHash(DbClient.getProfile())
		self.assertNotEqual(firstHash, secondHash, "Profile hash should have changed")
Esempio n. 7
0
	def testGetProfile(self):
		# Delete whole profiles table
		DbClient._getProfileTable().remove({})
		self.assertEqual(DbClient._getProfileTable().count(), 0, "Profiles table should be empty")
		# Add own profile
		myTorId = "ABC123DEF456GH78"
		myprofile = {"name" : "Constantin Taylor", "keyid" : "someKeyId", "displayName" : "Me",
					"status" : "self", "ownprofile" : True}
		DbClient.updateContact(myTorId, myprofile)
		self.assertEqual(DbClient._getProfileTable().count(), 1, "Profiles table should have my profile in it")

		profileFromDb = DbClient.getProfile(None)
		self.assertIsNotNone(profileFromDb, "Couldn't retrieve own profile")
		profileFromDb = DbClient.getProfile(myTorId)
		self.assertIsNotNone(profileFromDb, "Couldn't retrieve profile using own id")

		# Initiate contact with a new person
		otherTorId = "PQR123STU456VWX78"
		otherName = "Olivia Barnacles"
		DbClient.updateContact(otherTorId, {"status" : "untrusted", "keyid" : "donotknow", "name" : otherName})
		self.assertEqual(DbClient._getProfileTable().count(), 2, "Profiles table should have 2 profiles")
		self.assertEqual(DbClient.getMessageableContacts().count(), 1, "Profiles table should have 1 messageable")
		self.assertEqual(DbClient.getTrustedContacts().count(), 0, "Profiles table should have 0 trusted")
		profileFromDb = DbClient.getProfile(otherTorId)
		self.assertIsNotNone(profileFromDb, "Couldn't retrieve profile using other id")
		self.assertEqual(profileFromDb.get("name", None), otherName, "Profile name doesn't match what was stored")
		self.assertEqual(profileFromDb.get("status", None), "untrusted", "Profile status doesn't match what was stored")

		# Update existing record, change status
		DbClient.updateContact(otherTorId, {"status" : "trusted"})
		self.assertEqual(DbClient._getProfileTable().count(), 2, "Profiles table should still have 2 profiles")
		profileFromDb = DbClient.getProfile(otherTorId)
		self.assertIsNotNone(profileFromDb, "Couldn't retrieve profile using other id")
		self.assertEqual(profileFromDb.get("status", None), "trusted", "Profile status should have been updated")
		self.assertEqual(DbClient.getMessageableContacts().count(), 1, "Profiles table should have 1 messageable")
		self.assertEqual(DbClient.getTrustedContacts().count(), 1, "Profiles table should have 1 trusted")

		# Delete other contact
		DbClient.updateContact(otherTorId, {"status" : "deleted"})
		self.assertEqual(DbClient.getMessageableContacts().count(), 0, "Profiles table should have 0 messageable")
		self.assertEqual(DbClient.getTrustedContacts().count(), 0, "Profiles table should have 0 trusted")
		self.assertFalse(DbClient.hasFriends(), "Shouldn't have any friends any more")
	def dealWithAsymmetricMessage(message):
		'''Decide what to do with the given asymmetric message'''
		if message.senderId == MessageShuffler.getOwnTorId():
			print("*** Shouldn't receive a message from myself!")
			return
		# Sort message according to type
		if message.messageType == Message.TYPE_CONTACT_RESPONSE:
			print("Received a contact accept from", message.senderId, "name", message.senderName)
			if MessageShuffler._isProfileStatusOk(message.senderId, ['pending', 'requested', 'untrusted']):
				print(message.senderName, "'s public key is", message.senderKey)
				ContactMaker.handleReceiveAccept(message.senderId, message.senderName, message.senderKey)
				# Call DbClient to store new message in inbox
				rowToStore = {"messageType":"contactresponse", "fromId":message.senderId,
					"fromName":message.senderName, "messageBody":message.introMessage, "accepted":True,
					"messageRead":False, "messageReplied":False, "timestamp":message.timestamp,
					"recipients":MessageShuffler.getOwnTorId()}
				DbClient.addMessageToInbox(rowToStore)
			elif MessageShuffler._isProfileStatusOk(message.senderId, [None, 'blocked']):
				print("Received a contact response but I didn't send them a request!")
				print("Encrypted contents are:", message.encryptedContents)
				rowToStore = {"messageType":"contactresponse", "fromId":message.senderId,
					"fromName":message.senderName, "messageBody":message.introMessage, "accepted":True,
					"timestamp":message.timestamp, "encryptedMsg":message.encryptedContents}
				DbClient.addMessageToPendingContacts(rowToStore)
		elif message.messageType == Message.TYPE_STATUS_NOTIFY:
			if message.online:
				print("One of our contacts has just come online- ", message.senderId,
					"and hash is", message.profileHash)
				prof = DbClient.getProfile(userid=message.senderId, extend=False)
				if prof:
					storedHash = prof.get("profileHash", "empty")
					if message.profileHash != storedHash:
						reply = InfoRequestMessage(infoType=InfoRequestMessage.INFO_PROFILE)
						reply.recipients = [message.senderId]
						DbClient.addMessageToOutbox(reply)
					if message.ping:
						print("Now sending back a pong, too")
						reply = StatusNotifyMessage(online=True, ping=False, profileHash=None)
						reply.recipients = [message.senderId]
						DbClient.addMessageToOutbox(reply)
					else:
						print("It's already a pong so I won't reply")
				Contacts.comeOnline(message.senderId)
			else:
				print("One of our contacts is going offline -", message.senderId)
				Contacts.goneOffline(message.senderId)
		elif message.messageType == Message.TYPE_INFO_REQUEST:
			print("I've received an info request message for type", message.infoType)
			if MessageShuffler._isProfileStatusOk(message.senderId, ['trusted']):
				reply = InfoResponseMessage(message.messageType)
				reply.recipients = [message.senderId]
				DbClient.addMessageToOutbox(reply)
		elif message.messageType == Message.TYPE_INFO_RESPONSE:
			if message.profile and MessageShuffler._isProfileStatusOk(message.senderId, ['trusted', 'untrusted']):
				if message.profileHash:
					message.profile['profileHash'] = message.profileHash
				DbClient.updateContact(message.senderId, message.profile)
		elif message.messageType == Message.TYPE_ASYM_MESSAGE:
			print("It's a general kind of message, this should go in the Inbox, right?")
			if MessageShuffler._isProfileStatusOk(message.senderId, ['trusted', 'untrusted']):
				Contacts.comeOnline(message.senderId)
		else:
			# It's another asymmetric message type
			print("Hä?  What kind of asymmetric message type is that? ", message.messageType)
Esempio n. 9
0
	def handleDeleteContact(torId):
		'''For whatever reason, we don't trust this contact any more, so status is set to "deleted"'''
		if torId and torId != DbClient.getOwnTorId():
			DbClient.updateContact(torId, {"status" : "deleted"})
Esempio n. 10
0
	def handleReceiveDeny(torId):
		'''We have requested contact with another id, but this has been denied.
		So we need to update their status accordingly'''
		if torId and torId != DbClient.getOwnTorId():
			DbClient.updateContact(torId, {"status" : "deleted"})
Esempio n. 11
0
	def servePage(self, view, url, params):
		self.requirePageResources(['button-addperson.png', 'button-drawgraph.png', 'avatar-none.jpg'])
		DbClient.exportAvatars(Config.getWebCacheDir())
		if url == "/add" or url == "/add/":
			contents = self.generateAddPage()
			view.setHtml(contents)
			return
		elif url == "/submitaddrequest":
			print("Submit add request!:", url)
			if len(params) > 0:
				# request to add a new friend
				recipientid  = params.get('murmeliid', '')
				dispname     = params.get('displayname', '')
				intromessage = params.get('intromessage', '')
				if len(recipientid) == 16:
					# TODO: How to react if: person already added (untrusted/trusted); request already sent (requested)
					# update the database accordingly
					ContactMaker.handleInitiate(recipientid, dispname)
					print("I should send an add request to '%s' now." % recipientid)
					outmsg = message.ContactRequestMessage(introMessage=intromessage)
					outmsg.recipients = [recipientid]
					DbClient.addMessageToOutbox(outmsg)
				else:
					print("Hmm, show an error message here?")
				# in any case, go back to contact list
				url = "/" + recipientid
				# ensure that picture is generated for new id
				DbClient.exportAvatars(Config.getWebCacheDir())
		contents = None
		userid   = None
		pageParams = {}
		# Split url into components /userid/command
		command = [i for i in url.split("/") if i != ""]
		if len(command) > 0 and len(command[0]) == 16 and re.match("([a-zA-Z0-9]+)$", command[0]):
			userid = command[0]
			# check for command edit or submit-edit
			if len(command) == 2:
				if command[1] == "edit":
					contents = self.generateListPage(doEdit=True, userid=userid) # show edit fields
				elif command[1] == "submitedit":
					DbClient.updateContact(userid, params)
					# don't generate contents, go back to details
				elif command[1] == "delete":
					ContactMaker.handleDeleteContact(userid)
					userid = None
				elif command[1] == "checkfingerprint":
					contents = self.generateFingerprintsPage(userid)
				elif command[1] == "checkedfingerprint":
					givenAnswer = int(params.get('answer', -1))
					fc = self._makeFingerprintChecker(userid)
					expectedAnswer = fc.getCorrectAnswer()
					if expectedAnswer == givenAnswer:
						ContactMaker.keyFingerprintChecked(userid)
						# Show page again
						contents = self.generateFingerprintsPage(userid)
					else:
						# Add a message to show when the list page is re-generated
						pageParams['fingerprint_check_failed'] = True

		# If we haven't got any contents yet, then do a show details
		if not contents:
			# Show details for selected userid (or for self if userid is None)
			contents = self.generateListPage(doEdit=False, userid=userid, extraParams=pageParams)

		view.setHtml(contents)
Esempio n. 12
0
	def setupOwnProfile(keyId):
		DbClient.useTestTables()
		DbClient.deleteOwnProfile()
		DbClient.updateContact(TestUtils._ownTorId, {"status":"self", "ownprofile":True,
			"keyid":keyId, "name":"Geoffrey Lancaster", "displayName":"Me",
			"description":"Ä fictitious person with a couple of Umläute in his description."})