provide a keychange operation to rebase an identity on a new keypair
This commit is contained in:
parent
5ed4ed2246
commit
6a7fa6bf54
@ -67,6 +67,7 @@ require_once('include/bbcode.php');
|
||||
* location channel_id
|
||||
* request channel_id xchan_hash message_id
|
||||
* rating xlink_id
|
||||
* keychange channel_id
|
||||
*
|
||||
*/
|
||||
|
||||
@ -144,6 +145,20 @@ class Notifier {
|
||||
$packet_type = 'request';
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif($cmd === 'keychange') {
|
||||
$channel = channelx_by_n($item_id);
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d",
|
||||
intval($item_id)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$recipients[] = $rr['abook_xchan'];
|
||||
}
|
||||
}
|
||||
$private = false;
|
||||
$packet_type = 'keychange';
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif($cmd == 'permission_update' || $cmd == 'permission_create') {
|
||||
// Get the (single) recipient
|
||||
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
|
||||
@ -570,12 +585,17 @@ class Notifier {
|
||||
|
||||
}
|
||||
|
||||
$hash = random_string();
|
||||
$hash = random_string();
|
||||
$packet = null;
|
||||
$pmsg = '';
|
||||
|
||||
if($packet_type === 'refresh' || $packet_type === 'purge') {
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
}
|
||||
if($packet_type === 'keychange') {
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
|
||||
}
|
||||
elseif($packet_type === 'request') {
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
|
||||
@ -589,7 +609,8 @@ class Notifier {
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'notify' => $packet
|
||||
'notify' => $packet,
|
||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||
));
|
||||
}
|
||||
else {
|
||||
|
@ -12,6 +12,8 @@ interface IHandler {
|
||||
|
||||
function Request($data);
|
||||
|
||||
function Rekey($sender,$data);
|
||||
|
||||
function AuthCheck($data,$encrypted);
|
||||
|
||||
function Purge($sender,$recipients);
|
||||
|
@ -120,6 +120,10 @@ class Receiver {
|
||||
$this->handler->Notify($this->data);
|
||||
break;
|
||||
|
||||
case 'rekey':
|
||||
$this->handler->Rekey($this->sender, $this->data);
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->response['message'] = 'Not implemented';
|
||||
json_return_and_die($this->response);
|
||||
|
@ -20,6 +20,10 @@ class ZotHandler implements IHandler {
|
||||
zot_reply_message_request($data);
|
||||
}
|
||||
|
||||
function Rekey($sender,$data) {
|
||||
zot_rekey_request($sender,$data);
|
||||
}
|
||||
|
||||
function AuthCheck($data,$encrypted) {
|
||||
zot_reply_auth_check($data,$encrypted);
|
||||
}
|
||||
|
@ -454,6 +454,105 @@ function create_identity($arr) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
function change_channel_keys($channel) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
|
||||
$stored = [];
|
||||
|
||||
$key = new_keypair(4096);
|
||||
|
||||
$sig = base64url_encode(rsa_sign($channel['channel_guid'],$key['prvkey']));
|
||||
$hash = make_xchan_hash($channel['channel_guid'],$sig);
|
||||
|
||||
$stored['old_guid'] = $channel['channel_guid'];
|
||||
$stored['old_guid_sig'] = $channel['channel_guid_sig'];
|
||||
$stored['old_key'] = $channel['channel_pubkey'];
|
||||
$stored['old_hash'] = $channel['channel_hash'];
|
||||
|
||||
$stored['new_key'] = $key['pubkey'];
|
||||
$stored['new_sig'] = base64url_encode(rsa_sign($key['pubkey'],$channel['channel_prvkey']));
|
||||
|
||||
// Save this info for the notifier to collect
|
||||
|
||||
set_pconfig($channel['channel_id'],'system','keychange',$stored);
|
||||
|
||||
$r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', channel_hash = '%s' where channel_id = %d",
|
||||
dbesc($key['prvkey']),
|
||||
dbesc($key['pubkey']),
|
||||
dbesc($sig),
|
||||
dbesc($hash),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(! $r) {
|
||||
return $ret;
|
||||
}
|
||||
$r = q("select * from channel where channel_id = %d",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$ret['message'] = t('Unable to retrieve modified identity');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$modified = $r[0];
|
||||
|
||||
$h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ",
|
||||
dbesc($stored['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(),$modifed['channel_prvkey']));
|
||||
hubloc_store_lowlevel($hv);
|
||||
}
|
||||
}
|
||||
|
||||
$x = q("select * from xchan where xchan_hash = '%s' ",
|
||||
dbesc($stored['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'] = $key['pubkey'];
|
||||
xchan_store_lowlevel($xv);
|
||||
$newxchan = $xv;
|
||||
}
|
||||
}
|
||||
|
||||
$a = q("select * from abook where abook_xchan = '%s' and abook_self = 1",
|
||||
dbesc($stored['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,$stored);
|
||||
|
||||
Zotlabs\Daemon\Master::Summon(array('Notifier', 'keychange', $channel['channel_id']));
|
||||
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set default channel to be used on login.
|
||||
*
|
||||
|
@ -137,3 +137,232 @@ function xchan_fetch($arr) {
|
||||
}
|
||||
|
||||
|
||||
function xchan_change_key($oldx,$newx,$data) {
|
||||
|
||||
$r = q("update abook set abook_xchan = '%s' where abook_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update abconfig set xchan = '%s' where xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update group_member set xchan = '%s' where xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update chat set chat_xchan = '%s' where chat_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update chatpresence set cp_xchan = '%s' where cp_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update event set event_xchan = '%s' where event_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update item set owner_xchan = '%s' where owner_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update item set author_xchan = '%s' where author_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update item set source_xchan = '%s' where source_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update mail set from_xchan = '%s' where from_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update mail set to_xchan = '%s' where to_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update shares set share_xchan = '%s' where share_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update source set src_channel_xchan = '%s' where src_channel_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update source set src_xchan = '%s' where src_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update xchat set xchat_xchan = '%s' where xchat_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update xconfig set xchan = '%s' where xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update xign set xchan = '%s' where xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update xlink set xlink_xchan = '%s' where xlink_xchan = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update xprof set xprof_hash = '%s' where xprof_hash = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("update xtag set xtag_hash = '%s' where xtag_hash = '%s'",
|
||||
dbsec($newx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
$r = q("select channel_id, channel_allow_cid, channel_deny_cid from channel where (channel_allow_cid like '%s' or channel_deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update channel set channel_allow_cid = '%s', channel_deny_cid = '%s' where channel_id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['channel_allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['channel_deny_cid'])),
|
||||
intval($rv['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select id, allow_cid, deny_cid from attach where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update attach set allow_cid = '%s', deny_cid = '%s' where id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select cr_id, allow_cid, deny_cid from chatroom where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update chatroom set allow_cid = '%s', deny_cid = '%s' where cr_id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['cr_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$r = q("select id, allow_cid, deny_cid from event where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update event set allow_cid = '%s', deny_cid = '%s' where id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$r = q("select id, allow_cid, deny_cid from item where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update item set allow_cid = '%s', deny_cid = '%s' where id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$r = q("select mitem_id, allow_cid, deny_cid from menu_item where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update menu_item set allow_cid = '%s', deny_cid = '%s' where mitem_id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['mitem_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$r = q("select obj_id, allow_cid, deny_cid from obj where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update obj set allow_cid = '%s', deny_cid = '%s' where obj_id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['obj_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select id, allow_cid, deny_cid from photo where (allow_cid like '%s' or deny_cid like '%s') ",
|
||||
dbesc($oldx['xchan_hash']),
|
||||
dbesc($oldx['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$z = q("update photo set allow_cid = '%s', deny_cid = '%s' where id = %d",
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])),
|
||||
dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])),
|
||||
intval($rv['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -3757,6 +3757,50 @@ function zot_reply_message_request($data) {
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
function zot_rekey_request($sender,$data) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
|
||||
// newsig is newkey signed with oldkey
|
||||
|
||||
// The original xchan will remain. In Zot/Receiver we will have imported the new xchan and hubloc to verify
|
||||
// the packet authenticity. What we will do now is verify that the keychange operation was signed by the
|
||||
// oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the
|
||||
// old xchan_hash.
|
||||
|
||||
if((! $data['oldkey']) && (! $data['oldsig']) && (! $data['newkey']) && (! $data['newsig']))
|
||||
json_return_and_die($ret);
|
||||
|
||||
$oldhash = make_xchan_hash($data['old_guid'],$data['old_guid_sig']);
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($oldhash)
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$xchan = $r[0];
|
||||
|
||||
if(! rsa_verify($data['newkey'],base64url_decode($data['newsig']),$xchan['xchan_pubkey'])) {
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$newhash = make_xchan_hash($sender['guid'],$sender['guid_sig']);
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($newhash)
|
||||
);
|
||||
|
||||
$newxchan = $r[0];
|
||||
|
||||
xchan_change_key($xchan,$newxchan,$data);
|
||||
|
||||
$ret['success'] = true;
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
function zotinfo($arr) {
|
||||
|
||||
|
Reference in New Issue
Block a user