]> git.mxchange.org Git - friendica.git/blobdiff - mod/dfrn_notify.php
Ensure that public contacts can't create toplevel posts
[friendica.git] / mod / dfrn_notify.php
index a0ac506769be364ec10d7960598f9f75c8d59063..a43c316b0c3c9d241f618d23c42e35fc8008d037 100644 (file)
@@ -7,15 +7,65 @@
  */
 
 use Friendica\App;
+use Friendica\Core\Config;
+use Friendica\Core\System;
+use Friendica\Database\DBM;
+use Friendica\Model\Contact;
+use Friendica\Protocol\DFRN;
+use Friendica\Protocol\Diaspora;
 
-require_once('include/items.php');
-require_once('include/dfrn.php');
-require_once('include/event.php');
-
-require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
+require_once 'include/items.php';
 
 function dfrn_notify_post(App $a) {
        logger(__function__, LOGGER_TRACE);
+
+       $postdata = file_get_contents('php://input');
+
+       if (empty($_POST) || !empty($postdata)) {
+               $data = json_decode($postdata);
+               if (is_object($data)) {
+                       $nick = defaults($a->argv, 1, '');
+                       $user = dba::selectFirst('user', [], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]);
+                       if (!DBM::is_result($user)) {
+                               System::httpExit(500);
+                       }
+                       $msg = Diaspora::decodeRaw($user, $postdata);
+
+                       // Check if the user has got this contact
+                       $cid = getIdForURL($msg['author'], $user['uid']);
+                       if (!$cid) {
+                               // Otherwise there should be a public contact
+                               $cid = 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, 'Processed');
+               } else {
+                       require_once 'mod/salmon.php';
+                       salmon_post($a, $postdata);
+               }
+       }
+
        $dfrn_id      = ((x($_POST,'dfrn_id'))      ? notags(trim($_POST['dfrn_id']))   : '');
        $dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version']    : 2.0);
        $challenge    = ((x($_POST,'challenge'))    ? notags(trim($_POST['challenge'])) : '');
@@ -45,9 +95,9 @@ function dfrn_notify_post(App $a) {
                dbesc($dfrn_id),
                dbesc($challenge)
        );
-       if (! dbm::is_result($r)) {
+       if (! DBM::is_result($r)) {
                logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge);
-               xml_status(3, 'Could not match challenge');
+               System::xmlExit(3, 'Could not match challenge');
        }
 
        $r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s'",
@@ -69,7 +119,7 @@ function dfrn_notify_post(App $a) {
                        $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
                        break;
                default:
-                       xml_status(3, 'Invalid direction');
+                       System::xmlExit(3, 'Invalid direction');
                        break; // NOTREACHED
        }
 
@@ -93,9 +143,9 @@ function dfrn_notify_post(App $a) {
                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);
-               xml_status(3, 'Contact not found');
+               System::xmlExit(3, 'Contact not found');
                //NOTREACHED
        }
 
@@ -121,24 +171,19 @@ function dfrn_notify_post(App $a) {
 
        // if contact's ssl policy changed, update our links
 
-       fix_contact_ssl_policy($importer,$ssl_policy);
+       $importer = Contact::updateSslPolicy($importer, $ssl_policy);
 
        logger('dfrn_notify: received notify from ' . $importer['name'] . ' for ' . $importer['username']);
        logger('dfrn_notify: data: ' . $data, LOGGER_DATA);
 
        if ($dissolve == 1) {
-
-               /*
-                * Relationship is dissolved permanently
-                */
-
-               require_once('include/Contact.php');
-               contact_remove($importer['id']);
+               // Relationship is dissolved permanently
+               Contact::remove($importer['id']);
                logger('relationship dissolved : ' . $importer['name'] . ' dissolved ' . $importer['username']);
-               xml_status(0, 'relationship dissolved');
+               System::xmlExit(0, 'relationship dissolved');
        }
 
-       $rino = get_config('system', 'rino_encrypt');
+       $rino = Config::get('system', 'rino_encrypt');
        $rino = intval($rino);
 
        logger("Local rino version: " .  $rino, LOGGER_DEBUG);
@@ -147,9 +192,9 @@ function dfrn_notify_post(App $a) {
 
                // if local rino is lower than remote rino, abort: should not happen!
                // but only for $remote_rino > 1, because old code did't send rino version
-               if ($rino_remote_version > 1 && $rino < $rino_remote) {
+               if ($rino_remote > 1 && $rino < $rino_remote) {
                        logger("rino version '$rino_remote' is lower than supported '$rino'");
-                       xml_status(0, "rino version '$rino_remote' is lower than supported '$rino'");
+                       System::xmlExit(0, "rino version '$rino_remote' is lower than supported '$rino'");
                }
 
                $rawkey = hex2bin(trim($key));
@@ -170,49 +215,23 @@ function dfrn_notify_post(App $a) {
                        }
                }
 
-               #logger('rino: received key : ' . $final_key);
-
                switch($rino_remote) {
                        case 0:
                        case 1:
-                               /*
-                                *we got a key. old code send only the key, without RINO version.
-                                * we assume RINO 1 if key and no RINO version
-                                */
-                               $data = dfrn::aes_decrypt(hex2bin($data), $final_key);
-                               break;
-                       case 2:
-                               try {
-                                       $data = Crypto::decrypt(hex2bin($data), $final_key);
-                               } catch (InvalidCiphertext $ex) { // VERY IMPORTANT
-                                       /*
-                                        * Either:
-                                        *   1. The ciphertext was modified by the attacker,
-                                        *   2. The key is wrong, or
-                                        *   3. $ciphertext is not a valid ciphertext or was corrupted.
-                                        * Assume the worst.
-                                        */
-                                       logger('The ciphertext has been tampered with!');
-                                       xml_status(0, 'The ciphertext has been tampered with!');
-                               } catch (Ex\CryptoTestFailed $ex) {
-                                       logger('Cannot safely perform dencryption');
-                                       xml_status(0, 'CryptoTestFailed');
-                               } catch (Ex\CannotPerformOperation $ex) {
-                                       logger('Cannot safely perform decryption');
-                                       xml_status(0, 'Cannot safely perform decryption');
-                               }
+                               // we got a key. old code send only the key, without RINO version.
+                               // we assume RINO 1 if key and no RINO version
+                               $data = DFRN::aesDecrypt(hex2bin($data), $final_key);
                                break;
                        default:
                                logger("rino: invalid sent version '$rino_remote'");
-                               xml_status(0, "Invalid sent version '$rino_remote'");
+                               System::xmlExit(0, "Invalid sent version '$rino_remote'");
                }
 
-
                logger('rino: decrypted data: ' . $data, LOGGER_DATA);
        }
 
-       $ret = dfrn::import($data, $importer);
-       xml_status($ret, 'Processed');
+       $ret = DFRN::import($data, $importer);
+       System::xmlExit($ret, 'Processed');
 
        // NOTREACHED
 }
@@ -283,7 +302,7 @@ function dfrn_notify_content(App $a) {
                                dbesc($a->argv[1])
                );
 
-               if (! dbm::is_result($r)) {
+               if (! DBM::is_result($r)) {
                        $status = 1;
                }
 
@@ -312,7 +331,7 @@ function dfrn_notify_content(App $a) {
                $encrypted_id = bin2hex($encrypted_id);
 
 
-               $rino = get_config('system', 'rino_encrypt');
+               $rino = Config::get('system', 'rino_encrypt');
                $rino = intval($rino);
 
                logger("Local rino version: ". $rino, LOGGER_DEBUG);