Beispiel #1
0
def decode_sig(sig, msg_data, callback):
	if DEBUG > 2: print '--> Starting decode_sig'

	keyobj = Key()
	if DEBUG > 2: print 'Creating keyobj', keyobj

	# _ga_import_sig
	(magic, sig) = gale_pack.pop_data(sig, len(SIG_MAGIC))
	if SIG_MAGIC != magic:
		pygale.call_error_handler("invalid signature format")
		keyobj.set_verified(0)
		callback(keyobj)
		return
	(siglen, sig) = gale_pack.pop_int(sig)
	if siglen > GALE_SIGNATURE_LEN:
		pygale.call_error_handler('invalid signature format')
		keyobj.set_verified(0)
		callback(keyobj)
		return
	(sigdata, sig) = gale_pack.pop_data(sig, siglen)

	# These are the keybits doing the signing
	(keydata, sig) = gale_pack.pop_data(sig, len(sig))
	keyobj.setdata(keydata)
		
	# Try to find a public key for this signature
	if DEBUG > 2: print 'decode_sig: importing key'
	import_pubkey(keyobj, lambda k, d=sigdata,
		m=msg_data, c=callback: decode_sig2(k, d, m, c))
Beispiel #2
0
def decode_sig4(key, sigdata, msg_data, callback):
	if key.public() is not None:
		if DEBUG: print 'decode_sig4: key found', key.name()
		# We found something via AKD
		if verify_sig(key, sigdata, msg_data):
			# And it verifies!
			if DEBUG: print 'decode_sig4: %s verifies OK' % key.name()
			key.set_verified(1)
			authcache.save_pubkey_todisk(key)
			callback(key)
			return
		else:
			if DEBUG: print 'decode_sig4: %s does not verify' % key.name()
			key.setpublic(None)
			key.set_verified(0)
			callback(key)
			return
	else:
		# Otherwise, give up!
		if DEBUG: print 'decode_sig4: no key found for', key.name()
		pygale.call_error_handler("Warning: no public key for %s" %
			key.name())
		key.set_verified(0)
		callback(key)
		return
Beispiel #3
0
	def fetch_url3(self):
		# Data ready for reading
		while 1:
			read, write, ex = select.select([self.sock], [], [], 0)
			if self.sock in read:
				try:
					chunk = self.sock.recv(1024)
				except socket.error, e:
					pygale.call_error_handler('Error fetching %s: %s'
						% (self.url, e))
					engine.engine.del_callback(self.sock)
					engine.engine.del_timeout(self.timeout_handle)
					self.callback(None)
					return
				if not chunk:
					# Server closed connection
					self.cleanup()
					return
				self.data = self.data + chunk
				if self.maxsize and len(self.data) > self.maxsize:
					# We've seen enough
					self.cleanup()
					return
			else:
				return
Beispiel #4
0
	def fetch_url2(self):
		# Connected to socket; send request
		engine.engine.del_write_callback(self.sock)
		try:
			self.sock.send(self.urlrequest)
		except socket.error, e:
			pygale.call_error_handler('Error fetching %s: %s'
				% (self.url, e))
			self.callback(None)
			return
Beispiel #5
0
	def start_fetching(self):
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.sock = s
		s.setblocking(0)
		try:
			s.connect((self.host, self.port))
		except socket.error, e:
			if e[0] == errno.EINPROGRESS or e[0] == 10035:
				engine.engine.add_write_callback(s, self.fetch_url2)
			else:
				pygale.call_error_handler('Error fetching thumbnail: %s' %
					str(e))
Beispiel #6
0
def decode_done(key, upper_key, callback):
	if not key.verified():
		if DEBUG > 2: print 'decode_done: cannot use %s to verify %s' %\
			(key.name(), upper_key.name())
		pygale.call_error_handler('unable to verify signature %s' %
			key.name())
		callback(key)
		return
	if DEBUG > 1: print 'decode_done: key %s verified key %s' % (key.name(),
		upper_key.name())
	upper_key.set_verified(1)
	if DEBUG > 2: print 'decode_done: adding %s to memory cache' %\
		upper_key.name()
	authcache.add_to_memory_cache(upper_key)
	callback(upper_key)
	return
Beispiel #7
0
def verify_sig(key, sigdata, msg_data):
	"""Return 1 iff the sigdata is the signed message digest for msg_data,
	signed with the key key"""
	if DEBUG > 2: print 'verify_sig: verifying sig with key %s (%s)' %\
		(key, key.name())
	if key.trusted():
		if DEBUG > 2: print 'verify_sig: trusted key'
		key.set_verified(1)
		return 1
	assert key.public()

	context = openssl.evp.MD_CTX()
	context.VerifyInit(openssl.evp.md5())
	context.VerifyUpdate(msg_data)
	retval = context.VerifyFinal(sigdata, key.public())
	if retval != 1:
		pygale.call_error_handler(
			'signature %s does not verify (key mismatch?)' % key.name())
		return 0
	else:
		return 1
Beispiel #8
0
def import_pubkey(keyobj, callback, trust=0):
	if DEBUG > 2: print '--> Starting import_pubkey'
	keydata = keyobj.data()
	# _ga_import_pub
	# Back up the key to verify its signature, later
	save = keydata
	(magic, keydata) = gale_pack.pop_data(keydata, len(KEY_MAGIC))
	if KEY_MAGIC == magic:
		version = 1
	elif KEY_MAGIC2 == magic:
		version = 2
	elif KEY_MAGIC3 == magic:
		(subversion, keydata) = gale_pack.pop_data(keydata,
			len(SUBVERSION))
		if SUBVERSION == subversion:
			version = 3
		else:
			pygale.call_error_handler('Unsupported version 3 key format')
			keyobj.setpublic(None)
			keyobj.set_verified(0)
			callback(keyobj)
			return
	else:
		pygale.call_error_handler('Unsupported public key (bad magic)')
		keyobj.setpublic(None)
		keyobj.set_verified(0)
		callback(keyobj)
		return
	# version must be <= 3 at this point
	if DEBUG >= 3: print 'Public key version:', version

	if version > 1:
		(namelen, keydata) = gale_pack.pop_int(keydata)
		(pubkeyname, keydata) = gale_pack.pop_string(keydata, namelen,
			chars=1)
	else:	# version == 1
		(pubkeyname, keydata) = gale_pack.pop_nulltermstr(keydata)
	pubkeyname = flip_local_key_part(pubkeyname)
	if DEBUG > 2: print 'Unpacking public key named:', pubkeyname
	keyobj.setname(pubkeyname)
	if DEBUG > 2: print 'Setting name in %s to %s' % (`keyobj`, pubkeyname)
	keyobj.settrusted(trust)

	if len(keydata) == 0:
		if DEBUG: print 'Found stub key for', pubkeyname
		keyobj.setpublic(None)
		callback(keyobj)
		return

	# Otherwise, deal with a non-stub key
	# Special-case for different version keys.  Version 3 is the key with
	# fragments in it, which Dan introduced in 0.91b.
	if version == 3:
		fraglist = gale_pack.group_to_FragList(keydata, DAN_IS_STOOPID=1)

		# Verify key if it's signed
		if fraglist.has_key('security/signature'):
			# deal with only the first security/signature fragment
			sig = fraglist.get_binary_first('security/signature')
			(sig_len, sig) = gale_pack.pop_int(sig)
			(signature, sig) = gale_pack.pop_data(sig, sig_len)
			msg_data = sig
			new_fragments = gale_pack.group_to_FragList(sig)
			fraglist.update(new_fragments)
		else:
			signature = ''
			# TODO
			# This hacky setting of msg_data is to fix the bug later on
			# where we try to call decode_sig with msg_data.  I need to
			# dig into key formats more to find the right thing to do.
			msg_data = ''

		# TODO dangermouse
		# Redirects should not be handled here since the field contains
		# a *location* and not a key name
		if fraglist.get_text('key.redirect'):
			# Handle a key redirection: the field contains a *location*
			keyobj.set_redirect(fraglist.get_text_first('key.redirect'))

		# Use only the first instance of each fragment if it exists
		comment = fraglist.get_text_first('key.owner', 'Unspecified owner')
		time_sign = fraglist.get_time_first('key.signed', 0)
		time_expire = fraglist.get_time_first('key.expires', 0)
		rsa_keybits = fraglist.get_int_first('rsa.bits', 0)
		rsa_modulus = fraglist.get_binary_first('rsa.modulus', '')
		rsa_exponent = fraglist.get_binary_first('rsa.exponent', '')

		# Set the list of key members but do not look them up at this
		# point
		if fraglist.has_key('key.member'):
			keyobj.set_members(fraglist.get_text('key.member'))
		# Done unpacking version 3 key

	# Version 1 or 2 keys are packed binary data.
	elif version == 1 or version == 2:
		if version == 2:
			(comment, keydata) = gale_pack.pop_lenstr(keydata, chars=1)
		else:
			(comment, keydata) = gale_pack.pop_nulltermstr(keydata)
		if DEBUG > 2: print 'Found comment:', comment

		(rsa_keybits, keydata) = gale_pack.pop_int(keydata)
		(rsa_modulus, keydata) = gale_pack.pop_rle(keydata,
			GALE_RSA_MODULUS_LEN)
		(rsa_exponent, keydata) = gale_pack.pop_rle(keydata,
			GALE_RSA_MODULUS_LEN)
		if rsa_keybits > GALE_RSA_MODULUS_BITS:
			pygale.call_error_handler(
				'bad public key bit size %i' % rsa_keybits)
			keyobj.setpublic(None)
			keyobj.set_verified(0)
			callback(keyobj)
			return

		if version > 1 and keydata:
			(time_sign, keydata) = gale_pack.pop_time(keydata)
			(time_expire, keydata) = gale_pack.pop_time(keydata)
			if DEBUG > 2: print 'Key signed at:', time_sign.ctime()
			if DEBUG > 2: print 'Key expires at:', time_expire.ctime()
#			if time_expire <= time.time():
#				pygale.call_error_handler('found expired key for %s' %
#					pubkeyname)
#				callback(None)
#				return
		else:
			# no key timestamp checking in version 1
			pass
		signature = keydata

		# Done unpacking version 1 or version 2 key
	else:
		# unsupported version
		pygale.call_error_handler('unsupported key version: %i' %
			version)
		keyobj.setpublic(None)
		keyobj.set_verified(0)
		callback(keyobj)
		return
	
	# TODO: check for expired keys

	keyobj.setcomment(comment)
	if rsa_keybits:
		pubkey = openssl.evp.PKEY()
		pubkey.assign_RSA(openssl.rsa.RSA())
		pubkey.pkey.rsa.n = openssl.bn.bin2bn(rsa_modulus)
		pubkey.pkey.rsa.e = openssl.bn.bin2bn(rsa_exponent)
		keyobj.setpublic(pubkey)
	else:
		# No public key bits in this key
		keyobj.setpublic(None)

	# Import and validate the signature on this public key
	if not keyobj.trusted():
		if DEBUG > 2: print 'import_pubkey: Verifying sig'
		if version < 3:
			msg_data = save[:-len(keydata)]
		if not signature or not msg_data:
			pygale.call_error_handler('unsigned key %s' % keyobj.name())
			keyobj.setpublic(None)
			keyobj.set_verified(0)
			callback(keyobj)
			return
		decode_sig(signature, msg_data, lambda k, u=keyobj, c=callback:
			decode_done(k, u, c))

	else:
		if DEBUG: print 'Key is trusted; not verifying'
		keyobj.set_verified(1)
		callback(keyobj)
		return