Reworked dfrn_notify endpoint, added public endpoint

This commit is contained in:
Michael 2018-04-21 09:55:41 +00:00
parent e2ded28504
commit e61ed380f7

View file

@ -25,41 +25,23 @@ function dfrn_notify_post(App $a) {
$data = json_decode($postdata); $data = json_decode($postdata);
if (is_object($data)) { if (is_object($data)) {
$nick = defaults($a->argv, 1, ''); $nick = defaults($a->argv, 1, '');
$public = empty($nick);
if (!$public) {
$user = dba::selectFirst('user', [], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]); $user = dba::selectFirst('user', [], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]);
if (!DBM::is_result($user)) { if (!DBM::is_result($user)) {
System::httpExit(500); System::httpExit(500);
} }
} else {
// We don't need the user with public posts
$user = [];
}
$msg = Diaspora::decodeRaw($user, $postdata); $msg = Diaspora::decodeRaw($user, $postdata);
// Check if the user has got this contact if ($public) {
$cid = Contact::getIdForURL($msg['author'], $user['uid']); dfrn_dispatch_public($msg);
if (!$cid) { } else {
// Otherwise there should be a public contact dfrn_dispatch_private($user, $msg);
$cid = Contact::getIdForURL($msg['author']);
if (!$cid) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
} }
}
// We now have some contact, so we fetch it
$importer = dba::fetch_first("SELECT *, `name` as `senderName`
FROM `contact`
WHERE NOT `blocked` AND `id` = ? LIMIT 1",
$cid);
// This should never fail
if (!DBM::is_result($importer)) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
// Set the user id. This is important if this is a public contact
$importer['importer_uid'] = $user['uid'];
// Now we should be able to import it
$ret = DFRN::import($msg['message'], $importer);
System::xmlExit($ret, 'Done');
} else { } else {
require_once 'mod/salmon.php'; require_once 'mod/salmon.php';
salmon_post($a, $postdata); salmon_post($a, $postdata);
@ -91,19 +73,12 @@ function dfrn_notify_post(App $a) {
$dfrn_id = substr($dfrn_id, 2); $dfrn_id = substr($dfrn_id, 2);
} }
$r = q("SELECT * FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1", if (!dba::exists('challenge', ['dfrn-id' => $dfrn_id, 'challenge' => $challenge])) {
dbesc($dfrn_id), logger('could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge);
dbesc($challenge)
);
if (! DBM::is_result($r)) {
logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge);
System::xmlExit(3, 'Could not match challenge'); System::xmlExit(3, 'Could not match challenge');
} }
$r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s'", dba::delete('challenge', ['dfrn-id' => $dfrn_id, 'challenge' => $challenge]);
dbesc($dfrn_id),
dbesc($challenge)
);
// find the local user who owns this relationship. // find the local user who owns this relationship.
@ -143,8 +118,8 @@ function dfrn_notify_post(App $a) {
dbesc($a->argv[1]) dbesc($a->argv[1])
); );
if (! DBM::is_result($r)) { if (!DBM::is_result($r)) {
logger('dfrn_notify: contact not found for dfrn_id ' . $dfrn_id); logger('contact not found for dfrn_id ' . $dfrn_id);
System::xmlExit(3, 'Contact not found'); System::xmlExit(3, 'Contact not found');
//NOTREACHED //NOTREACHED
} }
@ -153,15 +128,11 @@ function dfrn_notify_post(App $a) {
$importer = $r[0]; $importer = $r[0];
logger("Remote rino version: ".$rino_remote." for ".$importer["url"], LOGGER_DEBUG);
if ((($writable != (-1)) && ($writable != $importer['writable'])) || ($importer['forum'] != $forum) || ($importer['prv'] != $prv)) { if ((($writable != (-1)) && ($writable != $importer['writable'])) || ($importer['forum'] != $forum) || ($importer['prv'] != $prv)) {
q("UPDATE `contact` SET `writable` = %d, forum = %d, prv = %d WHERE `id` = %d", $fields = ['writable' => ($writable == (-1)) ? $importer['writable'] : $writable,
intval(($writable == (-1)) ? $importer['writable'] : $writable), 'forum' => $forum, 'prv' => $prv];
intval($forum), dba::update('contact', $fields, ['id' => $importer['id']]);
intval($prv),
intval($importer['id'])
);
if ($writable != (-1)) { if ($writable != (-1)) {
$importer['writable'] = $writable; $importer['writable'] = $writable;
} }
@ -173,8 +144,7 @@ function dfrn_notify_post(App $a) {
$importer = Contact::updateSslPolicy($importer, $ssl_policy); $importer = Contact::updateSslPolicy($importer, $ssl_policy);
logger('dfrn_notify: received notify from ' . $importer['name'] . ' for ' . $importer['username']); logger('data: ' . $data, LOGGER_DATA);
logger('dfrn_notify: data: ' . $data, LOGGER_DATA);
if ($dissolve == 1) { if ($dissolve == 1) {
// Relationship is dissolved permanently // Relationship is dissolved permanently
@ -186,8 +156,6 @@ function dfrn_notify_post(App $a) {
$rino = Config::get('system', 'rino_encrypt'); $rino = Config::get('system', 'rino_encrypt');
$rino = intval($rino); $rino = intval($rino);
logger("Local rino version: " . $rino, LOGGER_DEBUG);
if (strlen($key)) { if (strlen($key)) {
// if local rino is lower than remote rino, abort: should not happen! // if local rino is lower than remote rino, abort: should not happen!
@ -198,24 +166,25 @@ function dfrn_notify_post(App $a) {
} }
$rawkey = hex2bin(trim($key)); $rawkey = hex2bin(trim($key));
logger('rino: md5 raw key: ' . md5($rawkey)); logger('rino: md5 raw key: ' . md5($rawkey), LOGGER_DATA);
$final_key = ''; $final_key = '';
if ($dfrn_version >= 2.1) { if ($dfrn_version >= 2.1) {
if ((($importer['duplex']) && strlen($importer['cprvkey'])) || (! strlen($importer['cpubkey']))) { if (($importer['duplex'] && strlen($importer['cprvkey'])) || !strlen($importer['cpubkey'])) {
openssl_private_decrypt($rawkey, $final_key, $importer['cprvkey']); openssl_private_decrypt($rawkey, $final_key, $importer['cprvkey']);
} else { } else {
openssl_public_decrypt($rawkey, $final_key, $importer['cpubkey']); openssl_public_decrypt($rawkey, $final_key, $importer['cpubkey']);
} }
} else { } else {
if ((($importer['duplex']) && strlen($importer['cpubkey'])) || (! strlen($importer['cprvkey']))) { if (($importer['duplex'] && strlen($importer['cpubkey'])) || !strlen($importer['cprvkey'])) {
openssl_public_decrypt($rawkey, $final_key, $importer['cpubkey']); openssl_public_decrypt($rawkey, $final_key, $importer['cpubkey']);
} else { } else {
openssl_private_decrypt($rawkey, $final_key, $importer['cprvkey']); openssl_private_decrypt($rawkey, $final_key, $importer['cprvkey']);
} }
} }
switch($rino_remote) { switch ($rino_remote) {
case 0: case 0:
case 1: case 1:
// we got a key. old code send only the key, without RINO version. // we got a key. old code send only the key, without RINO version.
@ -230,16 +199,80 @@ function dfrn_notify_post(App $a) {
logger('rino: decrypted data: ' . $data, LOGGER_DATA); logger('rino: decrypted data: ' . $data, LOGGER_DATA);
} }
logger('Importing post from ' . $importer['addr'] . ' to ' . $importer['nickname'] . ' with the RINO ' . $rino_remote . ' encryption.', LOGGER_DEBUG);
$ret = DFRN::import($data, $importer); $ret = DFRN::import($data, $importer);
System::xmlExit($ret, 'Processed'); System::xmlExit($ret, 'Processed');
// NOTREACHED // NOTREACHED
} }
function dfrn_dispatch_public($msg)
{
// Fetch the corresponding public contact
$contact = getDetailsByAddr($msg['author'], 0);
if (!$contact) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
// We now have some contact, so we fetch it
$importer = dba::fetch_first("SELECT *, `name` as `senderName`
FROM `contact`
WHERE NOT `blocked` AND `id` = ? LIMIT 1",
$cid);
// This should never fail
if (!DBM::is_result($importer)) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
logger('Importing post from ' . $msg['author'] . ' with the public envelope.', LOGGER_DEBUG);
// Now we should be able to import it
$ret = DFRN::import($msg['message'], $importer);
System::xmlExit($ret, 'Done');
}
function dfrn_dispatch_private($user, $msg)
{
// Check if the user has got this contact
$cid = Contact::getIdForURL($msg['author'], $user['uid']);
if (!$cid) {
// Otherwise there should be a public contact
$cid = Contact::getIdForURL($msg['author']);
if (!$cid) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
}
// We now have some contact, so we fetch it
$importer = dba::fetch_first("SELECT *, `name` as `senderName`
FROM `contact`
WHERE NOT `blocked` AND `id` = ? LIMIT 1",
$cid);
// This should never fail
if (!DBM::is_result($importer)) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
// Set the user id. This is important if this is a public contact
$importer['importer_uid'] = $user['uid'];
logger('Importing post from ' . $msg['author'] . ' to ' . $user['nickname'] . ' with the private envelope.', LOGGER_DEBUG);
// Now we should be able to import it
$ret = DFRN::import($msg['message'], $importer);
System::xmlExit($ret, 'Done');
}
function dfrn_notify_content(App $a) { function dfrn_notify_content(App $a) {
if(x($_GET,'dfrn_id')) { if (x($_GET,'dfrn_id')) {
/* /*
* initial communication from external contact, $direction is their direction. * initial communication from external contact, $direction is their direction.
@ -252,10 +285,10 @@ function dfrn_notify_content(App $a) {
$type = ""; $type = "";
$last_update = ""; $last_update = "";
logger('dfrn_notify: new notification dfrn_id=' . $dfrn_id); logger('new notification dfrn_id=' . $dfrn_id);
$direction = (-1); $direction = (-1);
if(strpos($dfrn_id,':') == 1) { if (strpos($dfrn_id,':') == 1) {
$direction = intval(substr($dfrn_id,0,1)); $direction = intval(substr($dfrn_id,0,1));
$dfrn_id = substr($dfrn_id,2); $dfrn_id = substr($dfrn_id,2);
} }
@ -264,23 +297,18 @@ function dfrn_notify_content(App $a) {
$status = 0; $status = 0;
$r = q("DELETE FROM `challenge` WHERE `expire` < " . intval(time())); dba::delete('challenge', ["`expire` < ?", time()]);
$r = q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` , `type`, `last_update` ) $fields = ['challenge' => $hash, 'dfrn-id' => $dfrn_id, 'expire' => time() + 90,
VALUES( '%s', '%s', %d, '%s', '%s' ) ", 'type' => $type, 'last_update' => $last_update];
dbesc($hash), dba::insert('challenge', $fields);
dbesc($dfrn_id),
intval(time() + 90 ),
dbesc($type),
dbesc($last_update)
);
logger('dfrn_notify: challenge=' . $hash, LOGGER_DEBUG); logger('challenge=' . $hash, LOGGER_DATA);
$sql_extra = ''; $sql_extra = '';
switch($direction) { switch($direction) {
case (-1): case (-1):
$sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id)); $sql_extra = sprintf(" AND (`issued-id` = '%s' OR `dfrn-id` = '%s') ", dbesc($dfrn_id), dbesc($dfrn_id));
$my_id = $dfrn_id; $my_id = $dfrn_id;
break; break;
case 0: case 0:
@ -302,11 +330,11 @@ function dfrn_notify_content(App $a) {
dbesc($a->argv[1]) dbesc($a->argv[1])
); );
if (! DBM::is_result($r)) { if (!DBM::is_result($r)) {
$status = 1; $status = 1;
} }
logger("Remote rino version: ".$rino_remote." for ".$r[0]["url"], LOGGER_DEBUG); logger("Remote rino version: ".$rino_remote." for ".$r[0]["url"], LOGGER_DATA);
$challenge = ''; $challenge = '';
$encrypted_id = ''; $encrypted_id = '';
@ -316,7 +344,7 @@ function dfrn_notify_content(App $a) {
$pub_key = trim($r[0]['pubkey']); $pub_key = trim($r[0]['pubkey']);
$dplx = intval($r[0]['duplex']); $dplx = intval($r[0]['duplex']);
if ((($dplx) && (strlen($prv_key))) || ((strlen($prv_key)) && (!(strlen($pub_key))))) { if (($dplx && strlen($prv_key)) || (strlen($prv_key) && !strlen($pub_key))) {
openssl_private_encrypt($hash, $challenge, $prv_key); openssl_private_encrypt($hash, $challenge, $prv_key);
openssl_private_encrypt($id_str, $encrypted_id, $prv_key); openssl_private_encrypt($id_str, $encrypted_id, $prv_key);
} elseif (strlen($pub_key)) { } elseif (strlen($pub_key)) {
@ -334,7 +362,7 @@ function dfrn_notify_content(App $a) {
$rino = Config::get('system', 'rino_encrypt'); $rino = Config::get('system', 'rino_encrypt');
$rino = intval($rino); $rino = intval($rino);
logger("Local rino version: ". $rino, LOGGER_DEBUG); logger("Local rino version: ". $rino, LOGGER_DATA);
// if requested rino is lower than enabled local rino, lower local rino version // if requested rino is lower than enabled local rino, lower local rino version
// if requested rino is higher than enabled local rino, reply with local rino // if requested rino is higher than enabled local rino, reply with local rino
@ -342,7 +370,7 @@ function dfrn_notify_content(App $a) {
$rino = $rino_remote; $rino = $rino_remote;
} }
if((($r[0]['rel']) && ($r[0]['rel'] != CONTACT_IS_SHARING)) || ($r[0]['page-flags'] == PAGE_COMMUNITY)) { if (($r[0]['rel'] && ($r[0]['rel'] != CONTACT_IS_SHARING)) || ($r[0]['page-flags'] == PAGE_COMMUNITY)) {
$perm = 'rw'; $perm = 'rw';
} else { } else {
$perm = 'r'; $perm = 'r';
@ -362,5 +390,4 @@ function dfrn_notify_content(App $a) {
killme(); killme();
} }
} }