X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=mod%2Freceive.php;h=95a51016757da46217f277e4b641799c43b1ec2c;hb=388847e1f371554f50613357de06cf4a6ec751c9;hp=e9af087de609a53bb6564ba3a54e423590806d6f;hpb=48ffa880f099b19052f18e399bf6af50780a24b0;p=friendica.git diff --git a/mod/receive.php b/mod/receive.php index e9af087de6..95a5101675 100644 --- a/mod/receive.php +++ b/mod/receive.php @@ -6,272 +6,71 @@ require_once('include/salmon.php'); -require_once('include/certfns.php'); +require_once('include/crypto.php'); +require_once('include/diaspora.php'); -function receive_return($val) { - if($val >= 400) - $err = 'Error'; - if($val >= 200 && $val < 300) - $err = 'OK'; - - logger('mod-diaspora returns ' . $val); - header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err); - killme(); - -} - - -function get_diaspora_key($uri) { - $key = ''; - - logger('Fetching diaspora key for: ' . $uri); - - $arr = lrdd($uri); - - if(is_array($arr)) { - foreach($arr as $a) { - if($a['@attributes']['rel'] === 'diaspora-public-key') { - $key = base64_decode($a['@attributes']['href']); - } - } - } - else { - return ''; - } - - if($key) - return rsatopem($key); - return ''; -} - function receive_post(&$a) { - if($a->argc != 3 || $a->argv[1] !== 'users') - receive_return(500); - - $guid = $a->argv[2]; - - $r = q("SELECT * FROM `user` WHERE `guid` = '%s' LIMIT 1", - dbesc($guid) - ); - if(! count($r)) - salmon_return(500); - - $importer = $r[0]; - - $xml = $_POST['xml']; - - logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA); - - if(! $xml) - receive_return(500); - - - $basedom = parse_xml_string($xml); - - if($basedom) - logger('parsed dom'); - - $atom = $basedom->children(NAMESPACE_ATOM1); - - logger('atom: ' . count($atom)); - $encrypted_header = json_decode(base64_decode($atom->encrypted_header)); - - print_r($encrypted_header); - - $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key); - $ciphertext = base64_decode($encrypted_header->ciphertext); - - logger('encrypted_aes: ' . print_r($encrypted_aes_key_bundle,true)); - logger('ciphertext: ' . print_r($ciphertext,true)); - - $outer_key_bundle = ''; - openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$localprvkey); - - logger('outer_bundle: ' . print_r($outer_key_bundle,true)); - - $j_outer_key_bundle = json_decode($outer_key_bundle); - - $outer_iv = base64_decode($j_outer_key_bundle->iv); - $outer_key = base64_decode($j_outer_key_bundle->key); - - $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv); - - $decrypted = pkcs5_unpad($decrypted); - - logger('decrypted: ' . print_r($decrypted,true)); - - /** - * $decrypted now contains something like - * - * - * 8e+G2+ET8l5BPuW0sVTnQw== - * UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU= - * - * Ryan Hughes - * acct:galaxor@diaspora.pirateship.org - * - * - */ - - $idom = parse_xml_string($decrypted,false); - - $inner_iv = base64_decode($idom->iv); - $inner_aes_key = base64_decode($idom->aes_key); - - logger('inner_iv: ' . $inner_iv); - $dom = $basedom->children(NAMESPACE_SALMON_ME); - - if($dom) - logger('have dom'); - - logger('dom: ' . count($dom)); - // figure out where in the DOM tree our data is hiding - - if($dom->provenance->data) - $base = $dom->provenance; - elseif($dom->env->data) - $base = $dom->env; - elseif($dom->data) - $base = $dom; - - if(! $base) { - logger('mod-diaspora: unable to locate salmon data in xml '); - dt_return(400); - } - - - // Stash the signature away for now. We have to find their key or it won't be good for anything. - $signature = base64url_decode($base->sig); - - logger('signature: ' . bin2hex($signature)); - - // unpack the data - - // strip whitespace so our data element will return to one big base64 blob - $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data); - // Add back the 60 char linefeeds - $lines = str_split($data,60); - $data = implode("\n",$lines); - - - // stash away some other stuff for later - - $type = $base->data[0]->attributes()->type[0]; - $keyhash = $base->sig[0]->attributes()->keyhash[0]; - $encoding = $base->encoding; - $alg = $base->alg; - - $signed_data = $data . (($data[-1] != "\n") ? "\n" : '') . '.' . base64url_encode($type) . "\n" . '.' . base64url_encode($encoding) . "\n" . '.' . base64url_encode($alg) . "\n"; - - logger('signed data: ' . $signed_data); - - // decode the data - $data = base64url_decode($data); - - // Now pull out the inner encrypted blob - - $inner_encrypted = base64_decode($data); - - $inner_decrypted = - $inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv); - - $inner_decrypted = pkcs5_unpad($inner_decrypted); - - logger('inner_decrypted: ' . $inner_decrypted); - - - - if(! $author_link) { - logger('mod-diaspora: Could not retrieve author URI.'); - receive_return(400); - } - - // Once we have the author URI, go to the web and try to find their public key - // *** or look it up locally *** - - logger('mod-diaspora: Fetching key for ' . $author_link ); - - // Get diaspora public key (pkcs#1) and convert to pkcs#8 - $key = get_diaspora_key($author_link); - - if(! $key) { - logger('mod-salmon: Could not retrieve author key.'); - receive_return(400); + $enabled = intval(get_config('system','diaspora_enabled')); + if(! $enabled) { + logger('mod-diaspora: disabled'); + http_status_exit(500); } - $verify = false; + $public = false; - if (version_compare(PHP_VERSION, '5.3.0', '>=')) { - $verify = openssl_verify($signed_data,$signature,$key,'sha256'); + if(($a->argc == 2) && ($a->argv[1] === 'public')) { + $public = true; } else { - // fallback sha256 verify for PHP < 5.3 - $rawsig = ''; - $hash = hash('sha256',$signed_data,true); - openssl_public_decrypt($signature,$rawsig,$key); - $verify = (($rawsig && substr($rawsig,-32) === $hash) ? true : false); - } - if(! $verify) { - logger('mod-diaspora: Message did not verify. Discarding.'); - receive_return(400); - } - - logger('mod-diaspora: Message verified.'); - - // If we reached this point, the message is good. - // Now let's figure out if the author is allowed to send us stuff. + if($a->argc != 3 || $a->argv[1] !== 'users') + http_status_exit(500); - $r = q("SELECT * FROM `contact` WHERE `network` = 'dspr' AND ( `url` = '%s' OR `alias` = '%s') - AND `uid` = %d LIMIT 1", - dbesc($author_link), - dbesc($author_link), - intval($importer['uid']) - ); - if(! count($r)) { - logger('mod-diaspora: Author unknown to us.'); - } + $guid = $a->argv[2]; - // is this a follower? Or have we ignored the person? - // If so we can not accept this post. + $r = q("SELECT * FROM `user` WHERE `guid` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1", + dbesc($guid) + ); + if(! count($r)) + http_status_exit(500); - if((count($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == CONTACT_IS_FOLLOWER) || ($r[0]['blocked']))) { - logger('mod-diaspora: Ignoring this author.'); - receive_return(202); - // NOTREACHED + $importer = $r[0]; } - require_once('include/items.php'); + // It is an application/x-www-form-urlencoded - // Placeholder for hub discovery. We shouldn't find any hubs - // since we supplied the fake feed header - and it doesn't have any. + logger('mod-diaspora: receiving post', LOGGER_DEBUG); - $hub = ''; + $xml = urldecode($_POST['xml']); - /** - * - * anti-spam measure: consume_feed will accept a follow activity from - * this person (and nothing else) if there is no existing contact record. - * - */ - - $contact_rec = ((count($r)) ? $r[0] : null); + logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA); + if(! $xml) + http_status_exit(500); + logger('mod-diaspora: message is okay', LOGGER_DEBUG); + $msg = diaspora_decode($importer,$xml); -// figure out what kind of diaspora message we have, and process accordingly. + logger('mod-diaspora: decoded', LOGGER_DEBUG); + logger('mod-diaspora: decoded msg: ' . print_r($msg,true), LOGGER_DATA); + if(! is_array($msg)) + http_status_exit(500); + logger('mod-diaspora: dispatching', LOGGER_DEBUG); + $ret = 0; + if($public) + diaspora_dispatch_public($msg); + else + $ret = diaspora_dispatch($importer,$msg); - receive_return(200); + http_status_exit(($ret) ? $ret : 200); + // NOTREACHED } - - -