Use locally cached Salmon keys for profiles

Please note that we're not yet actually caching them ourselves.
This commit is contained in:
Mikael Nordfeldth 2014-05-31 12:51:51 +02:00
parent 0c2134f9ad
commit 411f3b86a4
2 changed files with 46 additions and 8 deletions

View File

@ -59,12 +59,33 @@ class MagicEnvelope
} }
} }
/**
* Retrieve Salmon keypair first by checking local database, but
* if it's not found, attempt discovery if it has been requested.
*
* @param Profile $profile The profile we're looking up keys for.
* @param boolean $discovery Network discovery if no local cache?
*/
public function getKeyPair(Profile $profile, $discovery=false) {
$magicsig = Magicsig::getKV('user_id', $profile->id);
if ($discovery && !$magicsig instanceof Magicsig) {
$signer_uri = $profile->getUri();
if (empty($signer_uri)) {
throw new ServerException(sprintf('Profile missing URI (id==%d)', $profile->id));
}
$magicsig = $this->discoverKeyPair($signer_uri);
} elseif (!$magicsig instanceof Magicsig) { // No discovery request, so we'll give up.
throw new ServerException(sprintf('No public key found for profile (id==%d)', $profile->id));
}
return $magicsig;
}
/** /**
* Get the Salmon keypair from a URI, uses XRD Discovery etc. * Get the Salmon keypair from a URI, uses XRD Discovery etc.
* *
* @return Magicsig with loaded keypair * @return Magicsig with loaded keypair
*/ */
public function getKeyPair($signer_uri) public function discoverKeyPair($signer_uri)
{ {
$disco = new Discovery(); $disco = new Discovery();
@ -228,9 +249,11 @@ class MagicEnvelope
* *
* Details of failure conditions are dumped to output log and not exposed to caller. * Details of failure conditions are dumped to output log and not exposed to caller.
* *
* @param Profile $profile optional profile used to get locally cached public signature key.
*
* @return boolean * @return boolean
*/ */
public function verify() public function verify(Profile $profile=null)
{ {
if ($this->alg != 'RSA-SHA256') { if ($this->alg != 'RSA-SHA256') {
common_log(LOG_DEBUG, "Salmon error: bad algorithm"); common_log(LOG_DEBUG, "Salmon error: bad algorithm");
@ -243,8 +266,12 @@ class MagicEnvelope
} }
try { try {
$signer_uri = $this->getAuthorUri(); if ($profile instanceof Profile) {
$magicsig = $this->getKeyPair($signer_uri); $magicsig = $this->getKeyPair($profile, true); // Do discovery too if necessary
} else {
$signer_uri = $this->getAuthorUri();
$magicsig = $this->discoverKeyPair($signer_uri);
}
} catch (Exception $e) { } catch (Exception $e) {
common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage()); common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage());
return false; return false;

View File

@ -28,6 +28,8 @@ class SalmonAction extends Action
{ {
protected $needPost = true; protected $needPost = true;
protected $verified = false;
var $xml = null; var $xml = null;
var $activity = null; var $activity = null;
var $target = null; var $target = null;
@ -45,15 +47,24 @@ class SalmonAction extends Action
$envxml = file_get_contents('php://input'); $envxml = file_get_contents('php://input');
$magic_env = new MagicEnvelope($envxml); // parse incoming XML as a MagicEnvelope $magic_env = new MagicEnvelope($envxml); // parse incoming XML as a MagicEnvelope
if (!$magic_env->verify()) {
$entry = $magic_env->getPayload(); // Not cryptographically verified yet!
$this->activity = new Activity($entry->documentElement);
try {
$profile = Profile::fromUri($this->activity->actor->id);
$this->verified = $magic_env->verify($profile);
} catch (UnknownUriException $e) {
// If we don't know the profile, perform some discovery instead
$this->verified = $magic_env->verify();
}
if (!$this->verified) {
common_log(LOG_DEBUG, "Salmon signature verification failed."); common_log(LOG_DEBUG, "Salmon signature verification failed.");
// TRANS: Client error. // TRANS: Client error.
$this->clientError(_m('Salmon signature verification failed.')); $this->clientError(_m('Salmon signature verification failed.'));
} }
$entry = $magic_env->getPayload();
$this->activity = new Activity($entry->documentElement);
return true; return true;
} }