aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzotlabs <mike@macgirvin.com>2017-07-25 17:58:46 -0700
committerzotlabs <mike@macgirvin.com>2017-07-25 17:58:46 -0700
commit029cf6395dc1da503ebda7718cae30a8c19de691 (patch)
tree36b37a5c5a828e651df4eb33c622508cfe6e6a9c
parent08f15a6fc60023f739676d3751e2cd14cecf52a4 (diff)
downloadvolse-hubzilla-029cf6395dc1da503ebda7718cae30a8c19de691.tar.gz
volse-hubzilla-029cf6395dc1da503ebda7718cae30a8c19de691.tar.bz2
volse-hubzilla-029cf6395dc1da503ebda7718cae30a8c19de691.zip
sync key changes to clones
-rw-r--r--include/channel.php3
-rw-r--r--include/zot.php114
2 files changed, 111 insertions, 6 deletions
diff --git a/include/channel.php b/include/channel.php
index 23ceb1414..f6252f094 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -488,6 +488,7 @@ function change_channel_keys($channel) {
if(! $r) {
return $ret;
}
+
$r = q("select * from channel where channel_id = %d",
intval($channel['channel_id'])
);
@@ -532,6 +533,8 @@ function change_channel_keys($channel) {
}
}
+ build_sync_packet($channel['channel_id'], [ 'keychange' => $stored ]);
+
$a = q("select * from abook where abook_xchan = '%s' and abook_self = 1",
dbesc($stored['old_hash'])
);
diff --git a/include/zot.php b/include/zot.php
index f9682237e..a86948ef9 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -2949,6 +2949,11 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if($packet)
logger('packet: ' . print_r($packet, true),LOGGER_DATA, LOG_DEBUG);
+ $keychange = (($packet && array_key_exists('keychange',$packet)) ? true : false);
+ if($keychange) {
+ logger('keychange sync');
+ }
+
if(! $uid)
$uid = local_channel();
@@ -2962,6 +2967,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
return;
$channel = $r[0];
+
unset($channel['channel_password']);
unset($channel['channel_salt']);
@@ -2972,12 +2978,11 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
}
}
-
if(intval($channel['channel_removed']))
return;
$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'])
+ dbesc(($keychange) ? $packet['keychange']['old_hash'] : $channel['channel_hash'])
);
if(! $h)
@@ -3032,7 +3037,15 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
// don't pass these elements, they should not be synchronised
- $disallowed = array('channel_id','channel_account_id','channel_primary','channel_prvkey','channel_address','channel_deleted','channel_removed','channel_system');
+
+ $disallowed = [
+ 'channel_id','channel_account_id','channel_primary','channel_address',
+ 'channel_deleted','channel_removed','channel_system'
+ ];
+
+ if(! $keychange) {
+ $disallowed[] = 'channel_prvkey';
+ }
if(in_array($k,$disallowed))
continue;
@@ -3092,17 +3105,18 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
function process_channel_sync_delivery($sender, $arr, $deliveries) {
-
require_once('include/import.php');
/** @FIXME this will sync red structures (channel, pconfig and abook).
Eventually we need to make this application agnostic. */
- $result = array();
+ $result = [];
+
+ $keychange = ((array_key_exists('keychange',$arr)) ? true : false);
foreach ($deliveries as $d) {
$r = q("select * from channel where channel_hash = '%s' limit 1",
- dbesc($d['hash'])
+ dbesc(($keychange) ? $arr['keychange']['old_hash'] : $d['hash'])
);
if (! $r) {
@@ -3121,6 +3135,94 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
continue;
}
+ if($keychange) {
+ // verify the keychange operation
+ if(! rsa_verify($arr['channel']['channel_pubkey'],base64url_decode($arr['keychange']['new_sig']),$channel['channel_prvkey'])) {
+ logger('sync keychange: verification failed');
+ continue;
+ }
+
+ $sig = base64url_encode(rsa_sign($channel['channel_guid'],$arr['channel']['channel_prvkey']));
+ $hash = make_xchan_hash($channel['channel_guid'],$sig);
+
+
+ $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s',
+ channel_hash = '%s' where channel_id = %d",
+ dbesc($arr['channel']['channel_prvkey']),
+ dbesc($arr['channel']['channel_pubkey']),
+ dbesc($sig),
+ dbesc($hash),
+ intval($channel['channel_id'])
+ );
+ if(! $r) {
+ logger('keychange sync: channel update failed');
+ continue;
+ }
+
+ $r = q("select * from channel where channel_id = %d",
+ intval($channel['channel_id'])
+ );
+
+ if(! $r) {
+ logger('keychange sync: channel retrieve failed');
+ continue;
+ }
+
+ $channel = $r[0];
+
+ $h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ",
+ dbesc($arr['keychange']['old_hash']),
+ dbesc(z_root())
+ );
+
+ if($h) {
+ foreach($h as $hv) {
+ $hv['hubloc_guid_sig'] = $sig;
+ $hv['hubloc_hash'] = $hash;
+ $hv['hubloc_url_sig'] = base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey']));
+ hubloc_store_lowlevel($hv);
+ }
+ }
+
+ $x = q("select * from xchan where xchan_hash = '%s' ",
+ dbesc($arr['keychange']['old_hash'])
+ );
+
+ $check = q("select * from xchan where xchan_hash = '%s'",
+ dbesc($hash)
+ );
+
+ if(($x) && (! $check)) {
+ $oldxchan = $x[0];
+ foreach($x as $xv) {
+ $xv['xchan_guid_sig'] = $sig;
+ $xv['xchan_hash'] = $hash;
+ $xv['xchan_pubkey'] = $channel['channel_pubkey'];
+ xchan_store_lowlevel($xv);
+ $newxchan = $xv;
+ }
+ }
+
+ $a = q("select * from abook where abook_xchan = '%s' and abook_self = 1",
+ dbesc($arr['keychange']['old_hash'])
+ );
+
+ if($a) {
+ q("update abook set abook_xchan = '%s' where abook_id = %d",
+ dbesc($hash),
+ intval($a[0]['abook_id'])
+ );
+ }
+
+ xchan_change_key($oldxchan,$newxchan,$arr['keychange']);
+
+ // keychange operations can end up in a confused state if you try and sync anything else
+ // besides the channel keys, so ignore any other packets.
+
+ continue;
+ }
+
+
if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) {
foreach($arr['config'] as $cat => $k) {
foreach($arr['config'][$cat] as $k => $v)