Salmon posts can only be made for local users. More typing!

Since we of course don't have the remote party's private keys anyway.

I made some small fixes in Magicsig class too, removing unnecessary code.
This commit is contained in:
Mikael Nordfeldth 2014-06-02 19:44:57 +02:00
parent 2cd25039af
commit 537dff7987
6 changed files with 22 additions and 57 deletions

View File

@ -143,9 +143,9 @@ class Magicsig extends Managed_DataObject
* Warning: this can be very slow on systems without the GMP module. * Warning: this can be very slow on systems without the GMP module.
* Runtimes of 20-30 seconds are not unheard-of. * Runtimes of 20-30 seconds are not unheard-of.
* *
* @param int $user_id id of local user we're creating a key for * @param User $user the local user (since we don't have remote private keys)
*/ */
public function generate($user_id, $bits=1024) public function generate(User $user, $bits=1024)
{ {
$rsa = new Crypt_RSA(); $rsa = new Crypt_RSA();
@ -157,7 +157,7 @@ class Magicsig extends Managed_DataObject
$this->publicKey = new Crypt_RSA(); $this->publicKey = new Crypt_RSA();
$this->publicKey->loadKey($keypair['publickey']); $this->publicKey->loadKey($keypair['publickey']);
$this->user_id = $user_id; $this->user_id = $user->id;
$this->insert(); $this->insert();
} }
@ -179,25 +179,6 @@ class Magicsig extends Managed_DataObject
return 'RSA.' . $mod . '.' . $exp . $private_exp; return 'RSA.' . $mod . '.' . $exp . $private_exp;
} }
/**
* Decode a string representation of an RSA public key or keypair
* as a Magicsig object which can be used to sign or verify.
*
* @param string $text
* @return Magicsig
*/
public static function fromString($text)
{
$magic_sig = new Magicsig();
// remove whitespace
$text = preg_replace('/\s+/', '', $text);
$magic_sig->importKeys($text);
// Please note this object will be missing the user_id field
return $magic_sig;
}
/** /**
* importKeys will load the object's keypair string, which initiates * importKeys will load the object's keypair string, which initiates
* loadKey() and configures Crypt_RSA objects. * loadKey() and configures Crypt_RSA objects.
@ -206,10 +187,10 @@ class Magicsig extends Managed_DataObject
*/ */
public function importKeys($keypair=null) public function importKeys($keypair=null)
{ {
$keypair = $keypair ?: $this->keypair; $this->keypair = $keypair===null ? $this->keypair : preg_replace('/\s+/', '', $keypair);
// parse components // parse components
if (!preg_match('/RSA\.([^\.]+)\.([^\.]+)(\.([^\.]+))?/', $keypair, $matches)) { if (!preg_match('/RSA\.([^\.]+)\.([^\.]+)(\.([^\.]+))?/', $this->keypair, $matches)) {
common_debug('Magicsig error: RSA key not found in provided string.'); common_debug('Magicsig error: RSA key not found in provided string.');
throw new ServerException('RSA key not found in keypair string.'); throw new ServerException('RSA key not found in keypair string.');
} }
@ -241,7 +222,7 @@ class Magicsig extends Managed_DataObject
common_log(LOG_DEBUG, "Adding ".$type." key: (".$mod .', '. $exp .")"); common_log(LOG_DEBUG, "Adding ".$type." key: (".$mod .', '. $exp .")");
$rsa = new Crypt_RSA(); $rsa = new Crypt_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1; $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->setHash($this->getHash()); $rsa->setHash($this->getHash());
$rsa->modulus = new Math_BigInteger(Magicsig::base64_url_decode($mod), 256); $rsa->modulus = new Math_BigInteger(Magicsig::base64_url_decode($mod), 256);
$rsa->k = strlen($rsa->modulus->toBytes()); $rsa->k = strlen($rsa->modulus->toBytes());

View File

@ -289,17 +289,8 @@ class Ostatus_profile extends Managed_DataObject
* @param string $verb Activity::SUBSCRIBE or Activity::JOIN * @param string $verb Activity::SUBSCRIBE or Activity::JOIN
* @param Object $object object of the action; must define asActivityNoun($tag) * @param Object $object object of the action; must define asActivityNoun($tag)
*/ */
public function notify($actor, $verb, $object=null, $target=null) public function notify(Profile $actor, $verb, $object=null, $target=null)
{ {
if (!($actor instanceof Profile)) {
$type = gettype($actor);
if ($type == 'object') {
$type = get_class($actor);
}
// TRANS: Server exception.
// TRANS: %1$s is the method name the exception occured in, %2$s is the actor type.
throw new ServerException(sprintf(_m('Invalid actor passed to %1$s: %2$s.'),__METHOD__,$type));
}
if ($object == null) { if ($object == null) {
$object = $this; $object = $this;
} }
@ -340,8 +331,7 @@ class Ostatus_profile extends Managed_DataObject
$xml = $entry->getString(); $xml = $entry->getString();
common_log(LOG_INFO, "Posting to Salmon endpoint $this->salmonuri: $xml"); common_log(LOG_INFO, "Posting to Salmon endpoint $this->salmonuri: $xml");
$salmon = new Salmon(); Salmon::post($this->salmonuri, $xml, $actor->getUser());
$salmon->post($this->salmonuri, $xml, $actor);
} }
/** /**
@ -355,8 +345,7 @@ class Ostatus_profile extends Managed_DataObject
public function notifyActivity($entry, Profile $actor) public function notifyActivity($entry, Profile $actor)
{ {
if ($this->salmonuri) { if ($this->salmonuri) {
$salmon = new Salmon(); return Salmon::post($this->salmonuri, $this->notifyPrepXml($entry), $actor->getUser());
return $salmon->post($this->salmonuri, $this->notifyPrepXml($entry), $actor);
} }
common_debug(__CLASS__.' error: No salmonuri for Ostatus_profile uri: '.$this->uri); common_debug(__CLASS__.' error: No salmonuri for Ostatus_profile uri: '.$this->uri);

View File

@ -324,25 +324,21 @@ class MagicEnvelope
* on some systems. * on some systems.
* *
* @param string $text XML fragment to sign, assumed to be Atom * @param string $text XML fragment to sign, assumed to be Atom
* @param Profile $actor Profile of a local user to use as signer * @param User $user User who cryptographically signs $text
* *
* @return string XML string representation of magic envelope * @return string XML string representation of magic envelope
* *
* @throws Exception on bad profile input or key generation problems * @throws Exception on bad profile input or key generation problems
* @fixme if signing fails, this seems to return the original text without warning. Is there a reason for this? * @fixme if signing fails, this seems to return the original text without warning. Is there a reason for this?
*/ */
public static function signForProfile($text, Profile $actor) public static function signAsUser($text, User $user)
{ {
// We only generate keys for our local users of course, so let
// getUser throw an exception if the profile is not local.
$user = $actor->getUser();
// Find already stored key // Find already stored key
$magicsig = Magicsig::getKV('user_id', $user->id); $magicsig = Magicsig::getKV('user_id', $user->id);
if (!$magicsig instanceof Magicsig) { if (!$magicsig instanceof Magicsig) {
// No keypair yet, let's generate one. // No keypair yet, let's generate one.
$magicsig = new Magicsig(); $magicsig = new Magicsig();
$magicsig->generate($user->id); $magicsig->generate($user);
} }
$magic_env = self::signMessage($text, 'application/atom+xml', $magicsig); $magic_env = self::signMessage($text, 'application/atom+xml', $magicsig);

View File

@ -43,18 +43,18 @@ class Salmon
* *
* @param string $endpoint_uri * @param string $endpoint_uri
* @param string $xml string representation of payload * @param string $xml string representation of payload
* @param Profile $actor local user profile whose keys to sign with * @param User $user local user profile whose keys we sign with
* @return boolean success * @return boolean success
*/ */
public function post($endpoint_uri, $xml, Profile $actor) public static function post($endpoint_uri, $xml, User $user)
{ {
if (empty($endpoint_uri)) { if (empty($endpoint_uri)) {
common_debug('No endpoint URI for Salmon post to '.$actor->getUri()); common_debug('No endpoint URI for Salmon post to '.$user->getUri());
return false; return false;
} }
try { try {
$magic_env = MagicEnvelope::signForProfile($xml, $actor); $magic_env = MagicEnvelope::signAsUser($xml, $user);
$envxml = $magic_env->toXML(); $envxml = $magic_env->toXML();
} catch (Exception $e) { } catch (Exception $e) {
common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage()); common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage());
@ -73,7 +73,7 @@ class Salmon
} }
if ($response->getStatus() != 200) { if ($response->getStatus() != 200) {
common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s',
$actor->id, $endpoint_uri, $response->getStatus(), $response->getBody())); $user->id, $endpoint_uri, $response->getStatus(), $response->getBody()));
return false; return false;
} }

View File

@ -41,8 +41,7 @@ class SalmonQueueHandler extends QueueHandler
$actor = Profile::getKV($data['actor']); $actor = Profile::getKV($data['actor']);
$salmon = new Salmon(); Salmon::post($data['salmonuri'], $data['entry'], $actor->getUser());
$salmon->post($data['salmonuri'], $data['entry'], $actor);
// @fixme detect failure and attempt to resend // @fixme detect failure and attempt to resend
return true; return true;

View File

@ -51,7 +51,7 @@ echo "== Original entry ==\n\n";
print $entry; print $entry;
print "\n\n"; print "\n\n";
$magic_env = MagicEnvelope::signForProfile($entry, $profile); $magic_env = MagicEnvelope::signAsUser($entry, $profile->getUser());
$envxml = $magic_env->toXML(); $envxml = $magic_env->toXML();
echo "== Signed envelope ==\n\n"; echo "== Signed envelope ==\n\n";
@ -61,8 +61,8 @@ print "\n\n";
echo "== Testing local verification ==\n\n"; echo "== Testing local verification ==\n\n";
$magic_env = new MagicEnvelope($envxml); $magic_env = new MagicEnvelope($envxml);
$activity = new Activity($magic_env->getPayload()->documentElement); $activity = new Activity($magic_env->getPayload()->documentElement);
$profile = Profile::fromUri($activity->actor->id); $actprofile = Profile::fromUri($activity->actor->id);
$ok = $magic_env->verify($profile); $ok = $magic_env->verify($actprofile);
if ($ok) { if ($ok) {
print "OK\n\n"; print "OK\n\n";
} else { } else {
@ -86,7 +86,7 @@ if (have_option('--slap')) {
echo "== Remote salmon slap ==\n\n"; echo "== Remote salmon slap ==\n\n";
print "Sending signed Salmon slap to $url ...\n"; print "Sending signed Salmon slap to $url ...\n";
$ok = $salmon->post($url, $entry, $profile); $ok = Salmon::post($url, $entry, $profile->getUser());
if ($ok) { if ($ok) {
print "OK\n\n"; print "OK\n\n";
} else { } else {