Move around some code related to Magic_envelope and signing
This commit is contained in:
parent
aab7667cd5
commit
30a4393afa
|
@ -32,6 +32,8 @@ class MagicEnvelope
|
||||||
|
|
||||||
const NS = 'http://salmon-protocol.org/ns/magic-env';
|
const NS = 'http://salmon-protocol.org/ns/magic-env';
|
||||||
|
|
||||||
|
protected $actor = null; // Profile of user who has signed the envelope
|
||||||
|
|
||||||
protected $data = null; // When stored here it is _always_ base64url encoded
|
protected $data = null; // When stored here it is _always_ base64url encoded
|
||||||
protected $data_type = null;
|
protected $data_type = null;
|
||||||
protected $encoding = null;
|
protected $encoding = null;
|
||||||
|
@ -48,7 +50,7 @@ class MagicEnvelope
|
||||||
* @fixme may give fatal errors if some elements are missing or invalid XML
|
* @fixme may give fatal errors if some elements are missing or invalid XML
|
||||||
* @fixme calling DOMDocument::loadXML statically triggers warnings in strict mode
|
* @fixme calling DOMDocument::loadXML statically triggers warnings in strict mode
|
||||||
*/
|
*/
|
||||||
public function __construct($xml=null) {
|
public function __construct($xml=null, Profile $actor=null) {
|
||||||
if (!empty($xml)) {
|
if (!empty($xml)) {
|
||||||
$dom = new DOMDocument();
|
$dom = new DOMDocument();
|
||||||
if (!$dom->loadXML($xml)) {
|
if (!$dom->loadXML($xml)) {
|
||||||
|
@ -56,6 +58,15 @@ class MagicEnvelope
|
||||||
} elseif (!$this->fromDom($dom)) {
|
} elseif (!$this->fromDom($dom)) {
|
||||||
throw new ServerException('Could not load MagicEnvelope from DOM');
|
throw new ServerException('Could not load MagicEnvelope from DOM');
|
||||||
}
|
}
|
||||||
|
} elseif ($actor instanceof Profile) {
|
||||||
|
// So far we only allow setting with _either_ $xml _or_ $actor as that's
|
||||||
|
// all our circumstances require. But it may be confusing for new developers.
|
||||||
|
// The idea is that feeding XML must be followed by interpretation and then
|
||||||
|
// running $magic_env->verify($profile), just as in SalmonAction->prepare(...)
|
||||||
|
// and supplying an $actor (which right now has to be a User) will require
|
||||||
|
// defining the $data, $data_type etc. attributes manually afterwards before
|
||||||
|
// signing the envelope..
|
||||||
|
$this->setActor($actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +173,21 @@ class MagicEnvelope
|
||||||
*
|
*
|
||||||
* @throws Exception of various kinds on signing failure
|
* @throws Exception of various kinds on signing failure
|
||||||
*/
|
*/
|
||||||
public function signMessage($text, $mimetype, Magicsig $magicsig)
|
public function signMessage($text, $mimetype)
|
||||||
{
|
{
|
||||||
|
if (!$this->actor instanceof Profile) {
|
||||||
|
throw new ServerException('No profile to sign message with is set.');
|
||||||
|
} elseif (!$this->actor->isLocal()) {
|
||||||
|
throw new ServerException('Cannot sign magic envelopes with remote users since we have no private key.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find already stored key
|
||||||
|
$magicsig = Magicsig::getKV('user_id', $this->actor->getID());
|
||||||
|
if (!$magicsig instanceof Magicsig) {
|
||||||
|
// and if it doesn't exist, it is time to create one!
|
||||||
|
$magicsig = Magicsig::generate($this->actor->getUser());
|
||||||
|
}
|
||||||
|
assert($magicsig instanceof Magicsig);
|
||||||
assert($magicsig->privateKey instanceof Crypt_RSA);
|
assert($magicsig->privateKey instanceof Crypt_RSA);
|
||||||
|
|
||||||
// Prepare text and metadata for signing
|
// Prepare text and metadata for signing
|
||||||
|
@ -290,7 +314,12 @@ class MagicEnvelope
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $magicsig->verify($this->signingText(), $this->getSignature());
|
if (!$magicsig->verify($this->signingText(), $this->getSignature())) {
|
||||||
|
// TRANS: Client error when incoming salmon slap signature does not verify cryptographically.
|
||||||
|
throw new ClientException(_m('Salmon signature verification failed.'));
|
||||||
|
}
|
||||||
|
$this->setActor($profile);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,6 +352,22 @@ class MagicEnvelope
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setActor(Profile $actor)
|
||||||
|
{
|
||||||
|
if ($this->actor instanceof Profile) {
|
||||||
|
throw new ServerException('Cannot set a new actor profile for MagicEnvelope object.');
|
||||||
|
}
|
||||||
|
$this->actor = $actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getActor()
|
||||||
|
{
|
||||||
|
if (!$this->actor instanceof Profile) {
|
||||||
|
throw new ServerException('No actor set for this magic envelope.');
|
||||||
|
}
|
||||||
|
return $this->actor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given string as a signed MagicEnvelope XML document,
|
* Encode the given string as a signed MagicEnvelope XML document,
|
||||||
* using the keypair for the given local user profile. We can of
|
* using the keypair for the given local user profile. We can of
|
||||||
|
@ -342,16 +387,8 @@ class MagicEnvelope
|
||||||
*/
|
*/
|
||||||
public static function signAsUser($text, User $user)
|
public static function signAsUser($text, User $user)
|
||||||
{
|
{
|
||||||
// Find already stored key
|
$magic_env = new MagicEnvelope(null, $user->getProfile());
|
||||||
$magicsig = Magicsig::getKV('user_id', $user->id);
|
$magic_env->signMessage($text, 'application/atom+xml');
|
||||||
if (!$magicsig instanceof Magicsig) {
|
|
||||||
$magicsig = Magicsig::generate($user);
|
|
||||||
}
|
|
||||||
assert($magicsig instanceof Magicsig);
|
|
||||||
assert($magicsig->privateKey instanceof Crypt_RSA);
|
|
||||||
|
|
||||||
$magic_env = new MagicEnvelope();
|
|
||||||
$magic_env->signMessage($text, 'application/atom+xml', $magicsig);
|
|
||||||
|
|
||||||
return $magic_env;
|
return $magic_env;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,13 @@ class Salmon
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$magic_env = MagicEnvelope::signAsUser($xml, $user);
|
$magic_env = MagicEnvelope::signAsUser($xml, $user);
|
||||||
$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());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$envxml = $magic_env->toXML();
|
||||||
|
|
||||||
$headers = array('Content-Type: application/magic-envelope+xml');
|
$headers = array('Content-Type: application/magic-envelope+xml');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -73,8 +74,10 @@ class Salmon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diaspora wants a slightly different formatting on the POST (other Content-type, so body needs "xml=")
|
// Diaspora wants a slightly different formatting on the POST (other Content-type, so body needs "xml=")
|
||||||
|
// This also gives us the opportunity to send the specially formatted Diaspora salmon slap, which
|
||||||
|
// encrypts the content of me:data
|
||||||
if ($response->getStatus() === 422) {
|
if ($response->getStatus() === 422) {
|
||||||
common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. Diaspora? Will try again! Body: %s',
|
common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. We assume it is a Diaspora seed, will adapt and try again! Body: %s',
|
||||||
$user->id, $endpoint_uri, $response->getStatus(), $response->getBody()));
|
$user->id, $endpoint_uri, $response->getStatus(), $response->getBody()));
|
||||||
$headers = array('Content-Type: application/x-www-form-urlencoded');
|
$headers = array('Content-Type: application/x-www-form-urlencoded');
|
||||||
$client->setBody('xml=' . Magicsig::base64_url_encode($envxml));
|
$client->setBody('xml=' . Magicsig::base64_url_encode($envxml));
|
||||||
|
|
|
@ -79,12 +79,8 @@ class SalmonAction extends Action
|
||||||
$this->clientError($e->getMessage());
|
$this->clientError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cryptographic verification test
|
// Cryptographic verification test, throws exception on failure
|
||||||
if (!$magic_env->verify($this->actor)) {
|
$magic_env->verify($this->actor);
|
||||||
common_log(LOG_DEBUG, "Salmon signature verification failed.");
|
|
||||||
// TRANS: Client error.
|
|
||||||
$this->clientError(_m('Salmon signature verification failed.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user