forked from GNUsocial/gnu-social
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:
parent
2cd25039af
commit
537dff7987
@ -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());
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user