aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/conversation.php2
-rw-r--r--include/crypto.php112
-rw-r--r--include/zot.php318
3 files changed, 270 insertions, 162 deletions
diff --git a/include/conversation.php b/include/conversation.php
index 16eacd73e..0f61eea27 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -363,7 +363,7 @@ function localize_item(&$item){
if(intval($item['item_obscured'])
&& strlen($item['body']) && (! strpos($item['body'],'data'))) {
- $item['body'] = json_encode(crypto_encapsulate($item['body'],get_config('system','pubkey'), CRYPTO_ALGORITHM));
+ $item['body'] = z_obscure($item['body']);
}
}
diff --git a/include/crypto.php b/include/crypto.php
index c67c4a1ef..e9fa320d3 100644
--- a/include/crypto.php
+++ b/include/crypto.php
@@ -48,27 +48,115 @@ function pkcs5_unpad($text)
function AES256CBC_encrypt($data,$key,$iv) {
return openssl_encrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
-
}
function AES256CBC_decrypt($data,$key,$iv) {
return openssl_decrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function AES128CBC_encrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ return openssl_encrypt($data,'aes-128-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function AES128CBC_decrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ return openssl_decrypt($data,'aes-128-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function STD_encrypt($data,$key,$iv) {
+ $key = substr($key,0,32);
+ return openssl_encrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function STD_decrypt($data,$key,$iv) {
+ $key = substr($key,0,32);
+ return openssl_decrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+function CAST5CBC_encrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ $iv = substr($iv,0,8);
+ return openssl_encrypt($data,'cast5-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,8,"\0"));
+}
+
+function CAST5CBC_decrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ $iv = substr($iv,0,8);
+ return openssl_decrypt($data,'cast5-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,8,"\0"));
}
function crypto_encapsulate($data,$pubkey,$alg='aes256cbc') {
+ $fn = strtoupper($alg) . '_encrypt';
+
if($alg === 'aes256cbc')
return aes_encapsulate($data,$pubkey);
+ return other_encapsulate($data,$pubkey,$alg);
+
+}
+
+function other_encapsulate($data,$pubkey,$alg) {
+ if(! $pubkey)
+ logger('no key. data: ' . $data);
+
+ $fn = strtoupper($alg) . '_encrypt';
+ if(function_exists($fn)) {
+
+ // A bit hesitant to use openssl_random_pseudo_bytes() as we know
+ // it has been historically targeted by US agencies for 'weakening'.
+ // It is still arguably better than trying to come up with an
+ // alternative cryptographically secure random generator.
+ // There is little point in using the optional second arg to flag the
+ // assurance of security since it is meaningless if the source algorithms
+ // have been compromised. Also none of this matters if RSA has been
+ // compromised by state actors and evidence is mounting that this has
+ // already happened.
+
+ $key = openssl_random_pseudo_bytes(256);
+ $iv = openssl_random_pseudo_bytes(256);
+ $result['data'] = base64url_encode($fn($data,$key,$iv),true);
+ // log the offending call so we can track it down
+ if(! openssl_public_encrypt($key,$k,$pubkey)) {
+ $x = debug_backtrace();
+ logger('RSA failed. ' . print_r($x[0],true));
+ }
+
+ $result['alg'] = $alg;
+ $result['key'] = base64url_encode($k,true);
+ openssl_public_encrypt($iv,$i,$pubkey);
+ $result['iv'] = base64url_encode($i,true);
+ return $result;
+ }
+ else {
+ $x = [ 'data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data ];
+ call_hooks('other_encapsulate', $x);
+ return $x['result'];
+ }
+}
+
+function crypto_methods() {
+
+ // 'std' is the new project standard which is aes256cbc but transmits/receives 256-byte key and iv.
+ // aes256cbc is provided for compatibility with earlier zot implementations which assume 32-byte key and 16-byte iv.
+ // other_encapsulate() now produces these longer keys/ivs by default so that it is difficult to guess a
+ // particular implementation or choice of underlying implementations based on the key/iv length.
+ // The actual methods are responsible for deriving the actual key/iv from the provided parameters;
+ // possibly by truncation or segmentation - though many other methods could be used.
+
+ $r = [ 'std', 'aes256cbc', 'aes128cbc', 'cast5cbc' ];
+ call_hooks('crypto_methods',$r);
+ return $r;
+
}
function aes_encapsulate($data,$pubkey) {
if(! $pubkey)
logger('aes_encapsulate: no key. data: ' . $data);
- $key = random_string(32,RANDOM_STRING_TEXT);
- $iv = random_string(16,RANDOM_STRING_TEXT);
+ $key = openssl_random_pseudo_bytes(32);
+ $iv = openssl_random_pseudo_bytes(16);
$result['data'] = base64url_encode(AES256CBC_encrypt($data,$key,$iv),true);
// log the offending call so we can track it down
if(! openssl_public_encrypt($key,$k,$pubkey)) {
@@ -89,6 +177,22 @@ function crypto_unencapsulate($data,$prvkey) {
if($alg === 'aes256cbc')
return aes_unencapsulate($data,$prvkey);
+ return other_unencapsulate($data,$prvkey,$alg);
+
+}
+
+function other_unencapsulate($data,$prvkey,$alg) {
+ $fn = strtoupper($alg) . '_decrypt';
+ if(function_exists($fn)) {
+ openssl_private_decrypt(base64url_decode($data['key']),$k,$prvkey);
+ openssl_private_decrypt(base64url_decode($data['iv']),$i,$prvkey);
+ return $fn(base64url_decode($data['data']),$k,$i);
+ }
+ else {
+ $x = [ 'data' => $data, 'prvkey' => $prvkey, 'alg' => $alg, 'result' => $data ];
+ call_hooks('other_unencapsulate',$x);
+ return $x['result'];
+ }
}
@@ -315,7 +419,7 @@ function convert_salmon_key($key) {
function z_obscure($s) {
- return json_encode(crypto_encapsulate($s,get_config('system','pubkey'),CRYPTO_ALGORITHM));
+ return json_encode(crypto_encapsulate($s,get_config('system','pubkey')));
}
function z_unobscure($s) {
diff --git a/include/zot.php b/include/zot.php
index ee4836d6c..e29978908 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -110,20 +110,21 @@ function zot_get_hublocs($hash) {
* @param string $extra
* @returns string json encoded zot packet
*/
-function zot_build_packet($channel, $type = 'notify', $recipients = null, $remote_key = null, $secret = null, $extra = null) {
+function zot_build_packet($channel, $type = 'notify', $recipients = null, $remote_key = null, $methods = '', $secret = null, $extra = null) {
- $data = array(
+ $data = [
'type' => $type,
- 'sender' => array(
+ 'sender' => [
'guid' => $channel['channel_guid'],
'guid_sig' => base64url_encode(rsa_sign($channel['channel_guid'],$channel['channel_prvkey'])),
'url' => z_root(),
'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
'sitekey' => get_config('system','pubkey')
- ),
+ ],
'callback' => '/post',
- 'version' => ZOT_REVISION
- );
+ 'version' => ZOT_REVISION,
+ 'encryption' => crypto_methods()
+ ];
if ($recipients) {
for ($x = 0; $x < count($recipients); $x ++)
@@ -146,14 +147,46 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot
// Hush-hush ultra top-secret mode
- if ($remote_key) {
- $data = crypto_encapsulate(json_encode($data),$remote_key, CRYPTO_ALGORITHM);
+ if($remote_key) {
+ $algorithm = zot_best_algorithm($methods);
+ $data = crypto_encapsulate(json_encode($data),$remote_key, $algorithm);
}
return json_encode($data);
}
/**
+ * @brief choose best encryption function from those available on both sites
+ *
+ * @param string $methods
+ * comma separated list of encryption methods
+ * @return string first match from our site method preferences crypto_methods() array
+ * of a method which is common to both sites; or 'aes256cbc' if no matches are found.
+ */
+
+function zot_best_algorithm($methods) {
+
+ if($methods) {
+ $x = explode(',',$methods);
+ if($x) {
+ $y = crypto_methods();
+ if($y) {
+ foreach($y as $yv) {
+ $yv = trim($yv);
+ if(in_array($yv,$x)) {
+ return($yv);
+ }
+ }
+ }
+ }
+ }
+
+ return 'aes256cbc';
+}
+
+
+
+/**
* @brief
*
* @see z_post_url()
@@ -167,101 +200,11 @@ function zot_zot($url, $data) {
}
/**
- * @brief Look up information about channel.
- *
- * @param string $webbie
- * does not have to be host qualified e.g. 'foo' is treated as 'foo\@thishub'
- * @param array $channel
- * (optional), if supplied permissions will be enumerated specifically for $channel
- * @param boolean $autofallback
- * fallback/failover to http if https connection cannot be established. Default is true.
- *
- * @return array see z_post_url() and \ref Zotlabs::Zot::Finger "\\Zotlabs\\Zot\\Finger"
- */
-function zot_finger($webbie, $channel = null, $autofallback = true) {
-
- if (strpos($webbie,'@') === false) {
- $address = $webbie;
- $host = App::get_hostname();
- } else {
- $address = substr($webbie,0,strpos($webbie,'@'));
- $host = substr($webbie,strpos($webbie,'@')+1);
- if(strpos($host,'/'))
- $host = substr($host,0,strpos($host,'/'));
- }
-
- $xchan_addr = $address . '@' . $host;
-
- if ((! $address) || (! $xchan_addr)) {
- logger('zot_finger: no address :' . $webbie);
- return array('success' => false);
- }
- logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA, LOG_DEBUG);
-
- // potential issue here; the xchan_addr points to the primary hub.
- // The webbie we were called with may not, so it might not be found
- // unless we query for hubloc_addr instead of xchan_addr
-
- $r = q("select xchan.*, hubloc.* from xchan
- left join hubloc on xchan_hash = hubloc_hash
- where xchan_addr = '%s' and hubloc_primary = 1 limit 1",
- dbesc($xchan_addr)
- );
-
- if ($r) {
- $url = $r[0]['hubloc_url'];
-
- if ($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') {
- logger('zot_finger: alternate network: ' . $webbie);
- logger('url: '.$url.', net: '.var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG);
- return array('success' => false);
- }
- } else {
- $url = 'https://' . $host;
- }
-
- $rhs = '/.well-known/zot-info';
- $https = ((strpos($url,'https://') === 0) ? true : false);
-
- logger('zot_finger: ' . $address . ' at ' . $url, LOGGER_DEBUG);
-
- if ($channel) {
- $postvars = array(
- 'address' => $address,
- 'target' => $channel['channel_guid'],
- 'target_sig' => $channel['channel_guid_sig'],
- 'key' => $channel['channel_pubkey']
- );
-
- $result = z_post_url($url . $rhs,$postvars);
-
- if ((! $result['success']) && ($autofallback)) {
- if ($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_post_url('http://' . $host . $rhs,$postvars);
- }
- }
- } else {
- $rhs .= '?f=&address=' . urlencode($address);
-
- $result = z_fetch_url($url . $rhs);
- if ((! $result['success']) && ($autofallback)) {
- if ($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_fetch_url('http://' . $host . $rhs);
- }
- }
- }
-
- if (! $result['success'])
- logger('zot_finger: no results');
-
- return $result;
-}
-
-/**
* @brief Refreshes after permission changed or friending, etc.
*
+ * The top half of this function is similar to \Zotlabs\Zot\Finger::run() and could potentially be
+ * consolidated.
+ *
* zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified
* to fetch new permissions via a finger/discovery operation. This may result in a new connection
* (abook entry) being added to a local channel and it may result in auto-permissions being granted.
@@ -283,6 +226,7 @@ function zot_finger($webbie, $channel = null, $autofallback = true) {
*
* @returns boolean true if successful, else false
*/
+
function zot_refresh($them, $channel = null, $force = false) {
if (array_key_exists('xchan_network', $them) && ($them['xchan_network'] !== 'zot')) {
@@ -298,7 +242,8 @@ function zot_refresh($them, $channel = null, $force = false) {
if ($them['hubloc_url']) {
$url = $them['hubloc_url'];
- } else {
+ }
+ else {
$r = null;
// if they re-installed the server we could end up with the wrong record - pointing to the old install.
@@ -334,7 +279,7 @@ function zot_refresh($them, $channel = null, $force = false) {
$token = random_string();
- $postvars = array();
+ $postvars = [];
$postvars['token'] = $token;
@@ -395,11 +340,13 @@ function zot_refresh($them, $channel = null, $force = false) {
if($channel) {
if($j['permissions']['data']) {
- $permissions = crypto_unencapsulate(array(
+ $permissions = crypto_unencapsulate(
+ [
'data' => $j['permissions']['data'],
'key' => $j['permissions']['key'],
'iv' => $j['permissions']['iv'],
- 'alg' => $j['permissions']['alg']),
+ 'alg' => $j['permissions']['alg']
+ ],
$channel['channel_prvkey']);
if($permissions)
$permissions = json_decode($permissions,true);
@@ -521,12 +468,14 @@ function zot_refresh($them, $channel = null, $force = false) {
if($new_connection) {
if(! \Zotlabs\Access\Permissions::PermsCompare($new_perms,$previous_perms))
Zotlabs\Daemon\Master::Summon(array('Notifier','permission_create',$new_connection[0]['abook_id']));
- Zotlabs\Lib\Enotify::submit(array(
+ Zotlabs\Lib\Enotify::submit(
+ [
'type' => NOTIFY_INTRO,
'from_xchan' => $x['hash'],
'to_xchan' => $channel['channel_hash'],
- 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
- ));
+ 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
+ ]
+ );
if(intval($permissions['view_stream'])) {
if(intval(get_pconfig($channel['channel_id'],'perm_limits','send_stream') & PERMS_PENDING)
@@ -536,6 +485,7 @@ function zot_refresh($them, $channel = null, $force = false) {
/** If there is a default group for this channel, add this connection to it */
+
$default_group = $channel['channel_default_group'];
if($default_group) {
require_once('include/group.php');
@@ -581,6 +531,7 @@ function zot_refresh($them, $channel = null, $force = false) {
* @returns array|null null if site is blacklisted or not found, otherwise an
* array with an hubloc record
*/
+
function zot_gethub($arr, $multiple = false) {
if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) {
@@ -593,7 +544,7 @@ function zot_gethub($arr, $multiple = false) {
$limit = (($multiple) ? '' : ' limit 1 ');
$sitekey = ((array_key_exists('sitekey',$arr) && $arr['sitekey']) ? " and hubloc_sitekey = '" . protect_sprintf($arr['sitekey']) . "' " : '');
- $r = q("select * from hubloc
+ $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url
where hubloc_guid = '%s' and hubloc_guid_sig = '%s'
and hubloc_url = '%s' and hubloc_url_sig = '%s'
$sitekey $limit",
@@ -630,9 +581,10 @@ function zot_gethub($arr, $multiple = false) {
* * \b success boolean true or false
* * \b message (optional) error string only if success is false
*/
+
function zot_register_hub($arr) {
- $result = array('success' => false);
+ $result = [ 'success' => false ];
if($arr['url'] && $arr['url_sig'] && $arr['guid'] && $arr['guid_sig']) {
@@ -691,6 +643,7 @@ function zot_register_hub($arr) {
* * \e boolean \b success boolean true or false
* * \e string \b message (optional) error string only if success is false
*/
+
function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
call_hooks('import_xchan', $arr);
@@ -789,7 +742,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$what .= 'xchan ';
$changed = true;
}
- } else {
+ }
+ else {
$import_photos = true;
if((($arr['site']['directory_mode'] === 'standalone')
@@ -825,7 +779,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$changed = true;
}
- if ($import_photos) {
+ if($import_photos) {
require_once('include/photo/photo_driver.php');
@@ -834,9 +788,9 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1",
dbesc($xchan_hash)
);
- if ($local) {
+ if($local) {
$ph = z_fetch_url($arr['photo'], true);
- if ($ph['success']) {
+ if($ph['success']) {
$hash = import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']);
@@ -874,11 +828,12 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
false
);
}
- } else {
+ }
+ else {
$photos = import_xchan_photo($arr['photo'], $xchan_hash);
}
- if ($photos) {
- if ($photos[4]) {
+ if($photos) {
+ if($photos[4]) {
// importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
// This often happens when somebody joins the matrix with a bad cert.
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
@@ -889,7 +844,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
dbesc($photos[3]),
dbesc($xchan_hash)
);
- } else {
+ }
+ else {
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
where xchan_hash = '%s'",
dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
@@ -946,7 +902,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$what .= 'profile ';
$changed = true;
}
- } else {
+ }
+ else {
logger('import_xchan: profile not available - hiding');
// they may have made it private
$r = q("delete from xprof where xprof_hash = '%s'",
@@ -999,16 +956,17 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
* @param array $arr - output of z_post_url()
* @param array $outq - The queue structure attached to this request
*/
+
function zot_process_response($hub, $arr, $outq) {
- if (! $arr['success']) {
+ if(! $arr['success']) {
logger('zot_process_response: failed: ' . $hub);
return;
}
$x = json_decode($arr['body'], true);
- if (! $x) {
+ if(! $x) {
logger('zot_process_response: No json from ' . $hub);
logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA, LOG_DEBUG);
}
@@ -1066,6 +1024,7 @@ function zot_process_response($hub, $arr, $outq) {
* decrypted and json decoded notify packet from remote site
* @return array from zot_import()
*/
+
function zot_fetch($arr) {
logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
@@ -1083,16 +1042,18 @@ function zot_fetch($arr) {
}
foreach($ret_hubs as $ret_hub) {
- $data = array(
- 'type' => 'pickup',
- 'url' => z_root(),
- 'callback_sig' => base64url_encode(rsa_sign(z_root() . '/post',get_config('system','prvkey'))),
- 'callback' => z_root() . '/post',
- 'secret' => $arr['secret'],
- 'secret_sig' => base64url_encode(rsa_sign($arr['secret'],get_config('system','prvkey')))
- );
- $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey'], CRYPTO_ALGORITHM));
+ $data = [
+ 'type' => 'pickup',
+ 'url' => z_root(),
+ 'callback_sig' => base64url_encode(rsa_sign(z_root() . '/post', get_config('system','prvkey'))),
+ 'callback' => z_root() . '/post',
+ 'secret' => $arr['secret'],
+ 'secret_sig' => base64url_encode(rsa_sign($arr['secret'], get_config('system','prvkey')))
+ ];
+
+ $algorithm = zot_best_algorithm($ret_hub['site_crypto']);
+ $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey'], $algorithm));
$fetch = zot_zot($url,$datatosend);
@@ -1143,6 +1104,11 @@ function zot_import($arr, $sender_url) {
$data = json_decode(crypto_unencapsulate($data,get_config('system','prvkey')),true);
}
+ if(! is_array($data)) {
+ logger('decode error');
+ return array();
+ }
+
if(! $data['success']) {
if($data['message'])
logger('remote pickup failed: ' . $data['message']);
@@ -1168,6 +1134,12 @@ function zot_import($arr, $sender_url) {
logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG);
+ if(! is_array($i['notify'])) {
+ logger('decode error');
+ continue;
+ }
+
+
$hub = zot_gethub($i['notify']['sender']);
if((! $hub) || ($hub['hubloc_url'] != $sender_url)) {
logger('zot_import: potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true));
@@ -1358,6 +1330,7 @@ function zot_import($arr, $sender_url) {
* @param array $msg
* @return NULL|array
*/
+
function public_recips($msg) {
require_once('include/channel.php');
@@ -1567,6 +1540,7 @@ function allowed_public_recips($msg) {
* @param boolean $request (optional) default false
* @return array
*/
+
function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) {
$result = array();
@@ -1876,6 +1850,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
* * \e int \b mid
* @param int $uid
*/
+
function remove_community_tag($sender, $arr, $uid) {
if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM)))
@@ -1946,6 +1921,7 @@ function remove_community_tag($sender, $arr, $uid) {
* @param array $orig
* @param int $uid
*/
+
function update_imported_item($sender, $item, $orig, $uid) {
// If this is a comment being updated, remove any privacy information
@@ -1986,6 +1962,7 @@ function update_imported_item($sender, $item, $orig, $uid) {
* @param boolean $relay
* @return boolean|int post_id
*/
+
function delete_imported_item($sender, $item, $uid, $relay) {
logger('delete_imported_item invoked', LOGGER_DEBUG);
@@ -2003,13 +1980,14 @@ function delete_imported_item($sender, $item, $uid, $relay) {
intval($uid)
);
- if ($r) {
- if ($r[0]['author_xchan'] === $sender['hash'] || $r[0]['owner_xchan'] === $sender['hash'] || $r[0]['source_xchan'] === $sender['hash'])
+ if($r) {
+ if($r[0]['author_xchan'] === $sender['hash'] || $r[0]['owner_xchan'] === $sender['hash'] || $r[0]['source_xchan'] === $sender['hash'])
$ownership_valid = true;
$post_id = $r[0]['id'];
$item_found = true;
- } else {
+ }
+ else {
// perhaps the item is still in transit and the delete notification got here before the actual item did. Store it with the deleted flag set.
// item_store() won't try to deliver any notifications or start delivery chains if this flag is set.
@@ -2018,25 +1996,24 @@ function delete_imported_item($sender, $item, $uid, $relay) {
logger('delete received for non-existent item - storing item data.');
- /** @BUG $arr is undefined here, so this is dead code */
- if ($arr['author_xchan'] === $sender['hash'] || $arr['owner_xchan'] === $sender['hash'] || $arr['source_xchan'] === $sender['hash']) {
+ if($item['author_xchan'] === $sender['hash'] || $item['owner_xchan'] === $sender['hash'] || $item['source_xchan'] === $sender['hash']) {
$ownership_valid = true;
- $item_result = item_store($arr);
+ $item_result = item_store($item);
$post_id = $item_result['item_id'];
}
}
- if ($ownership_valid === false) {
+ if($ownership_valid === false) {
logger('delete_imported_item: failed: ownership issue');
return false;
}
require_once('include/items.php');
- if ($item_found) {
- if (intval($r[0]['item_deleted'])) {
+ if($item_found) {
+ if(intval($r[0]['item_deleted'])) {
logger('delete_imported_item: item was already deleted');
- if (! $relay)
+ if(! $relay)
return false;
// This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised
@@ -2147,6 +2124,7 @@ function process_mail_delivery($sender, $arr, $deliveries) {
* * \e string \b hash a xchan_hash
* @param array $arr
*/
+
function process_rating_delivery($sender, $arr) {
logger('process_rating_delivery: ' . print_r($arr,true));
@@ -2206,6 +2184,7 @@ function process_rating_delivery($sender, $arr) {
* @param array $arr
* @param array $deliveries (unused)
*/
+
function process_profile_delivery($sender, $arr, $deliveries) {
logger('process_profile_delivery', LOGGER_DEBUG);
@@ -2302,6 +2281,7 @@ function check_location_move($sender_hash,$locations) {
* @param boolean $absolute (optional) default false
* @return array
*/
+
function sync_locations($sender, $arr, $absolute = false) {
$ret = array();
@@ -2549,7 +2529,7 @@ function zot_encode_locations($channel) {
if(intval($channel['channel_removed']) && $hub['hubloc_url'] === z_root())
$hub['hubloc_deleted'] = 1;
- $ret[] = array(
+ $ret[] = [
'host' => $hub['hubloc_host'],
'address' => $hub['hubloc_addr'],
'primary' => (intval($hub['hubloc_primary']) ? true : false),
@@ -2558,7 +2538,7 @@ function zot_encode_locations($channel) {
'callback' => $hub['hubloc_callback'],
'sitekey' => $hub['hubloc_sitekey'],
'deleted' => (intval($hub['hubloc_deleted']) ? true : false)
- );
+ ];
}
}
@@ -2575,6 +2555,7 @@ function zot_encode_locations($channel) {
* @param number $suppress_update default 0
* @return boolean $updated if something changed
*/
+
function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
logger('import_directory_profile', LOGGER_DEBUG);
@@ -2709,6 +2690,7 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA
* @param string $hash
* @param array $keywords
*/
+
function import_directory_keywords($hash, $keywords) {
$existing = array();
@@ -2753,6 +2735,7 @@ function import_directory_keywords($hash, $keywords) {
* @param string $addr
* @param int $flags (optional) default 0
*/
+
function update_modtime($hash, $guid, $addr, $flags = 0) {
$dirmode = intval(get_config('system', 'directory_mode'));
@@ -2785,6 +2768,7 @@ function update_modtime($hash, $guid, $addr, $flags = 0) {
* @param string $pubkey
* @return boolean true if updated or inserted
*/
+
function import_site($arr, $pubkey) {
if( (! is_array($arr)) || (! $arr['url']) || (! $arr['url_sig']))
return false;
@@ -2852,7 +2836,7 @@ function import_site($arr, $pubkey) {
$site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false);
$site_realm = htmlspecialchars($arr['realm'],ENT_COMPAT,'UTF-8',false);
$site_project = htmlspecialchars($arr['project'],ENT_COMPAT,'UTF-8',false);
- $site_crypto = ((array_key_exists('encryption',$arr)) ? implode(',', htmlspecialchars($arr['encryption'],ENT_COMPAT,'UTF-8',false)) : '');
+ $site_crypto = ((array_key_exists('encryption',$arr) && is_array($arr['encryption'])) ? htmlspecialchars(implode(',',$arr['encryption']),ENT_COMPAT,'UTF-8',false) : '');
$site_version = ((array_key_exists('version',$arr)) ? htmlspecialchars($arr['version'],ENT_COMPAT,'UTF-8',false) : '');
// You can have one and only one primary directory per realm.
@@ -2947,6 +2931,7 @@ function import_site($arr, $pubkey) {
* @param array $packet (optional) default null
* @param boolean $groups_changed (optional) default false
*/
+
function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if(get_config('system','server_role') === 'basic')
@@ -2982,7 +2967,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if(intval($channel['channel_removed']))
return;
- $h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
+ $h = q("select hubloc.*, site.site_crypto from hubloc left join site on site_url = hubloc_url where hubloc_hash = '%s' and hubloc_deleted = 0",
dbesc($channel['channel_hash'])
);
@@ -3069,7 +3054,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
foreach($synchubs as $hub) {
$hash = random_string();
- $n = zot_build_packet($channel,'notify',$env_recips,$hub['hubloc_sitekey'],$hash);
+ $n = zot_build_packet($channel,'notify',$env_recips,$hub['hubloc_sitekey'],$hub['site_crypto'],$hash);
queue_insert(array(
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
@@ -3095,6 +3080,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
* @param array $deliveries
* @return array
*/
+
function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(get_config('system','server_role') === 'basic')
@@ -3569,6 +3555,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
* * \e string \b xchan_url
* @return string
*/
+
function get_rpost_path($observer) {
if(! $observer)
return '';
@@ -3584,6 +3571,7 @@ function get_rpost_path($observer) {
* @param array $x
* @return boolean|string return false or a hash
*/
+
function import_author_zot($x) {
$hash = make_xchan_hash($x['guid'],$x['guid_sig']);
@@ -3623,6 +3611,7 @@ function import_author_zot($x) {
* @param array $data
* @return array
*/
+
function zot_reply_message_request($data) {
$ret = array('success' => false);
@@ -3659,7 +3648,7 @@ function zot_reply_message_request($data) {
if ($messages) {
$env_recips = null;
- $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
+ $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hulob_url = site_url where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
dbesc($sender_hash)
);
if (! $r) {
@@ -3681,7 +3670,7 @@ function zot_reply_message_request($data) {
* create a notify packet and drop the actual message packet in the queue for pickup
*/
- $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id']));
+ $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto'],$hash,array('message_id' => $data['message_id']));
queue_insert(array(
'hash' => $hash,
@@ -3918,7 +3907,12 @@ function zotinfo($arr) {
$permissions['connected'] = true;
}
- $ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey, CRYPTO_ALGORITHM) : $permissions);
+ // encrypt this with the default aes256cbc since we cannot be sure at this point which
+ // algorithms are preferred for communications with the remote site; notably
+ // because ztarget refers to an xchan and we don't necessarily know the origination
+ // location.
+
+ $ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey) : $permissions);
if($permissions['view_profile'])
$ret['profile'] = $profile;
@@ -3948,6 +3942,8 @@ function zotinfo($arr) {
$ret['site']['directory_url'] = z_root() . '/dirsearch';
+ $ret['site']['encryption'] = crypto_methods();
+
// hide detailed site information if you're off the grid
if($dirmode != DIRECTORY_MODE_STANDALONE) {
@@ -3988,14 +3984,14 @@ function zotinfo($arr) {
$visible_plugins[] = $rr['aname'];
}
- $ret['site']['plugins'] = $visible_plugins;
- $ret['site']['sitehash'] = get_config('system','location_hash');
- $ret['site']['sitename'] = get_config('system','sitename');
- $ret['site']['sellpage'] = get_config('system','sellpage');
- $ret['site']['location'] = get_config('system','site_location');
- $ret['site']['realm'] = get_directory_realm();
- $ret['site']['project'] = Zotlabs\Lib\System::get_platform_name() . ' ' . Zotlabs\Lib\System::get_server_role();
- $ret['site']['version'] = Zotlabs\Lib\System::get_project_version();
+ $ret['site']['plugins'] = $visible_plugins;
+ $ret['site']['sitehash'] = get_config('system','location_hash');
+ $ret['site']['sitename'] = get_config('system','sitename');
+ $ret['site']['sellpage'] = get_config('system','sellpage');
+ $ret['site']['location'] = get_config('system','site_location');
+ $ret['site']['realm'] = get_directory_realm();
+ $ret['site']['project'] = Zotlabs\Lib\System::get_platform_name() . ' ' . Zotlabs\Lib\System::get_server_role();
+ $ret['site']['version'] = Zotlabs\Lib\System::get_project_version();
}
@@ -4322,7 +4318,15 @@ function zot_reply_pickup($data) {
}
}
- $encrypted = crypto_encapsulate(json_encode($ret),$sitekey, CRYPTO_ALGORITHM);
+ // this is a bit of a hack because we don't have the hubloc_url here, only the callback url.
+ // worst case is we'll end up using aes256cbc if they've got a different post endpoint
+
+ $x = q("select site_crypto from site where site_url = '%s' limit 1",
+ dbesc(str_replace('/post','',$data['callback']))
+ );
+ $algorithm = zot_best_algorithm(($x) ? $x[0]['site_crypto'] : '');
+
+ $encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm);
json_return_and_die($encrypted);
/* pickup: end */