issue #52 - try all matching hublocs for remote auth, not just the "best one".
This commit is contained in:
parent
a679081993
commit
8c16f12d7a
267
mod/post.php
267
mod/post.php
@ -119,7 +119,7 @@ function post_init(&$a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try and find a hubloc for the person attempting to auth
|
// Try and find a hubloc for the person attempting to auth
|
||||||
$x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' order by hubloc_id desc limit 1",
|
$x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' order by hubloc_id desc",
|
||||||
dbesc($address)
|
dbesc($address)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ function post_init(&$a) {
|
|||||||
$j = json_decode($ret['body'], true);
|
$j = json_decode($ret['body'], true);
|
||||||
if ($j)
|
if ($j)
|
||||||
import_xchan($j);
|
import_xchan($j);
|
||||||
$x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' order by hubloc_id desc limit 1",
|
$x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' order by hubloc_id desc",
|
||||||
dbesc($address)
|
dbesc($address)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -146,161 +146,169 @@ function post_init(&$a) {
|
|||||||
goaway($desturl);
|
goaway($desturl);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger('mod_zot: auth request received from ' . $x[0]['hubloc_addr'] );
|
|
||||||
|
|
||||||
// check credentials and access
|
foreach($x as $xx) {
|
||||||
|
logger('mod_zot: auth request received from ' . $xx['hubloc_addr'] );
|
||||||
|
|
||||||
// If they are already authenticated and haven't changed credentials,
|
// check credentials and access
|
||||||
// we can save an expensive network round trip and improve performance.
|
|
||||||
|
|
||||||
$remote = remote_channel();
|
// If they are already authenticated and haven't changed credentials,
|
||||||
$result = null;
|
// we can save an expensive network round trip and improve performance.
|
||||||
$remote_service_class = '';
|
|
||||||
$remote_level = 0;
|
|
||||||
$remote_hub = $x[0]['hubloc_url'];
|
|
||||||
$DNT = 0;
|
|
||||||
|
|
||||||
// Also check that they are coming from the same site as they authenticated with originally.
|
$remote = remote_channel();
|
||||||
|
$result = null;
|
||||||
|
$remote_service_class = '';
|
||||||
|
$remote_level = 0;
|
||||||
|
$remote_hub = $xx['hubloc_url'];
|
||||||
|
$DNT = 0;
|
||||||
|
|
||||||
$already_authed = ((($remote) && ($x[0]['hubloc_hash'] == $remote) && ($x[0]['hubloc_url'] === $_SESSION['remote_hub'])) ? true : false);
|
// Also check that they are coming from the same site as they authenticated with originally.
|
||||||
if($delegate && $delegate !== $_SESSION['delegate_channel'])
|
|
||||||
$already_authed = false;
|
|
||||||
|
|
||||||
$j = array();
|
$already_authed = ((($remote) && ($xx['hubloc_hash'] == $remote) && ($xx['hubloc_url'] === $_SESSION['remote_hub'])) ? true : false);
|
||||||
|
if($delegate && $delegate !== $_SESSION['delegate_channel'])
|
||||||
|
$already_authed = false;
|
||||||
|
|
||||||
if (! $already_authed) {
|
$j = array();
|
||||||
|
|
||||||
// Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the site private key
|
if (! $already_authed) {
|
||||||
// The actual channel sending the packet ($c[0]) is not important, but this provides a generic zot packet with a sender
|
|
||||||
// which can be verified
|
|
||||||
|
|
||||||
$p = zot_build_packet($c[0],$type = 'auth_check', array(array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig'])), $x[0]['hubloc_sitekey'], $sec);
|
// Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the site private key
|
||||||
if ($test) {
|
// The actual channel sending the packet ($c[0]) is not important, but this provides a generic zot packet with a sender
|
||||||
$ret['message'] .= 'auth check packet created using sitekey ' . $x[0]['hubloc_sitekey'] . EOL;
|
// which can be verified
|
||||||
$ret['message'] .= 'packet contents: ' . $p . EOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = zot_zot($x[0]['hubloc_callback'],$p);
|
$p = zot_build_packet($c[0],$type = 'auth_check', array(array('guid' => $xx['hubloc_guid'],'guid_sig' => $xx['hubloc_guid_sig'])), $xx['hubloc_sitekey'], $sec);
|
||||||
|
|
||||||
if (! $result['success']) {
|
|
||||||
logger('mod_zot: auth_check callback failed.');
|
|
||||||
if ($test) {
|
if ($test) {
|
||||||
$ret['message'] .= 'auth check request to your site returned .' . print_r($result, true) . EOL;
|
$ret['message'] .= 'auth check packet created using sitekey ' . $xx['hubloc_sitekey'] . EOL;
|
||||||
json_return_and_die($ret);
|
$ret['message'] .= 'packet contents: ' . $p . EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
goaway($desturl);
|
$result = zot_zot($xx['hubloc_callback'],$p);
|
||||||
}
|
|
||||||
$j = json_decode($result['body'], true);
|
|
||||||
if (! $j) {
|
|
||||||
logger('mod_zot: auth_check json data malformed.');
|
|
||||||
if($test) {
|
|
||||||
$ret['message'] .= 'json malformed: ' . $result['body'] . EOL;
|
|
||||||
json_return_and_die($ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($test) {
|
if (! $result['success']) {
|
||||||
$ret['message'] .= 'auth check request returned .' . print_r($j, true) . EOL;
|
logger('mod_zot: auth_check callback failed.');
|
||||||
}
|
|
||||||
|
|
||||||
if ($already_authed || $j['success']) {
|
|
||||||
if ($j['success']) {
|
|
||||||
// legit response, but we do need to check that this wasn't answered by a man-in-middle
|
|
||||||
if (! rsa_verify($sec . $x[0]['xchan_hash'],base64url_decode($j['confirm']),$x[0]['xchan_pubkey'])) {
|
|
||||||
logger('mod_zot: auth: final confirmation failed.');
|
|
||||||
if ($test) {
|
if ($test) {
|
||||||
$ret['message'] .= 'final confirmation failed. ' . $sec . print_r($j,true) . print_r($x[0],true);
|
$ret['message'] .= 'auth check request to your site returned .' . print_r($result, true) . EOL;
|
||||||
json_return_and_die($ret);
|
continue;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
goaway($desturl);
|
|
||||||
}
|
}
|
||||||
if (array_key_exists('service_class',$j))
|
$j = json_decode($result['body'], true);
|
||||||
$remote_service_class = $j['service_class'];
|
if (! $j) {
|
||||||
if (array_key_exists('level',$j))
|
logger('mod_zot: auth_check json data malformed.');
|
||||||
$remote_level = $j['level'];
|
if($test) {
|
||||||
if (array_key_exists('DNT',$j))
|
$ret['message'] .= 'json malformed: ' . $result['body'] . EOL;
|
||||||
$DNT = $j['DNT'];
|
continue;
|
||||||
}
|
|
||||||
// everything is good... maybe
|
|
||||||
if(local_channel()) {
|
|
||||||
|
|
||||||
// tell them to logout if they're logged in locally as anything but the target remote account
|
|
||||||
// in which case just shut up because they don't need to be doing this at all.
|
|
||||||
|
|
||||||
if ($a->channel['channel_hash'] != $x[0]['xchan_hash']) {
|
|
||||||
logger('mod_zot: auth: already authenticated locally as somebody else.');
|
|
||||||
notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry.') . EOL);
|
|
||||||
if ($test) {
|
|
||||||
$ret['message'] .= 'already logged in locally with a conflicting identity.' . EOL;
|
|
||||||
json_return_and_die($ret);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goaway($desturl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// log them in
|
|
||||||
|
|
||||||
if ($test) {
|
if ($test) {
|
||||||
$ret['success'] = true;
|
$ret['message'] .= 'auth check request returned .' . print_r($j, true) . EOL;
|
||||||
$ret['message'] .= 'Authentication Success!' . EOL;
|
|
||||||
json_return_and_die($ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$delegation_success = false;
|
if ($already_authed || $j['success']) {
|
||||||
if ($delegate) {
|
if ($j['success']) {
|
||||||
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where xchan_addr = '%s' limit 1",
|
// legit response, but we do need to check that this wasn't answered by a man-in-middle
|
||||||
dbesc($delegate)
|
if (! rsa_verify($sec . $xx['xchan_hash'],base64url_decode($j['confirm']),$xx['xchan_pubkey'])) {
|
||||||
|
logger('mod_zot: auth: final confirmation failed.');
|
||||||
|
if ($test) {
|
||||||
|
$ret['message'] .= 'final confirmation failed. ' . $sec . print_r($j,true) . print_r($xx,true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (array_key_exists('service_class',$j))
|
||||||
|
$remote_service_class = $j['service_class'];
|
||||||
|
if (array_key_exists('level',$j))
|
||||||
|
$remote_level = $j['level'];
|
||||||
|
if (array_key_exists('DNT',$j))
|
||||||
|
$DNT = $j['DNT'];
|
||||||
|
}
|
||||||
|
// everything is good... maybe
|
||||||
|
if(local_channel()) {
|
||||||
|
|
||||||
|
// tell them to logout if they're logged in locally as anything but the target remote account
|
||||||
|
// in which case just shut up because they don't need to be doing this at all.
|
||||||
|
|
||||||
|
if ($a->channel['channel_hash'] != $xx['xchan_hash']) {
|
||||||
|
logger('mod_zot: auth: already authenticated locally as somebody else.');
|
||||||
|
notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry.') . EOL);
|
||||||
|
if ($test) {
|
||||||
|
$ret['message'] .= 'already logged in locally with a conflicting identity.' . EOL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// log them in
|
||||||
|
|
||||||
|
if ($test) {
|
||||||
|
$ret['success'] = true;
|
||||||
|
$ret['message'] .= 'Authentication Success!' . EOL;
|
||||||
|
json_return_and_die($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
$delegation_success = false;
|
||||||
|
if ($delegate) {
|
||||||
|
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where xchan_addr = '%s' limit 1",
|
||||||
|
dbesc($delegate)
|
||||||
|
);
|
||||||
|
if ($r && intval($r[0]['channel_id'])) {
|
||||||
|
$allowed = perm_is_allowed($r[0]['channel_id'],$xx['xchan_hash'],'delegate');
|
||||||
|
if ($allowed) {
|
||||||
|
$_SESSION['delegate_channel'] = $r[0]['channel_id'];
|
||||||
|
$_SESSION['delegate'] = $xx['xchan_hash'];
|
||||||
|
$_SESSION['account_id'] = intval($r[0]['channel_account_id']);
|
||||||
|
require_once('include/security.php');
|
||||||
|
change_channel($r[0]['channel_id']);
|
||||||
|
$delegation_success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['authenticated'] = 1;
|
||||||
|
if (! $delegation_success) {
|
||||||
|
$_SESSION['visitor_id'] = $xx['xchan_hash'];
|
||||||
|
$_SESSION['my_url'] = $xx['xchan_url'];
|
||||||
|
$_SESSION['my_address'] = $address;
|
||||||
|
$_SESSION['remote_service_class'] = $remote_service_class;
|
||||||
|
$_SESSION['remote_level'] = $remote_level;
|
||||||
|
$_SESSION['remote_hub'] = $remote_hub;
|
||||||
|
$_SESSION['DNT'] = $DNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$arr = array('xchan' => $xx, 'url' => $desturl, 'session' => $_SESSION);
|
||||||
|
call_hooks('magic_auth_success',$arr);
|
||||||
|
$a->set_observer($xx);
|
||||||
|
require_once('include/security.php');
|
||||||
|
$a->set_groups(init_groups_visitor($_SESSION['visitor_id']));
|
||||||
|
info(sprintf( t('Welcome %s. Remote authentication successful.'),$xx['xchan_name']));
|
||||||
|
logger('mod_zot: auth success from ' . $xx['xchan_addr']);
|
||||||
|
q("update hubloc set hubloc_status = (hubloc_status | %d ) where hubloc_id = %d ",
|
||||||
|
intval(HUBLOC_WORKS),
|
||||||
|
intval($xx['hubloc_id'])
|
||||||
);
|
);
|
||||||
if ($r && intval($r[0]['channel_id'])) {
|
} else {
|
||||||
$allowed = perm_is_allowed($r[0]['channel_id'],$x[0]['xchan_hash'],'delegate');
|
if ($test) {
|
||||||
if ($allowed) {
|
$ret['message'] .= 'auth failure. ' . print_r($_REQUEST,true) . print_r($j,true) . EOL;
|
||||||
$_SESSION['delegate_channel'] = $r[0]['channel_id'];
|
continue;
|
||||||
$_SESSION['delegate'] = $x[0]['xchan_hash'];
|
|
||||||
$_SESSION['account_id'] = intval($r[0]['channel_account_id']);
|
|
||||||
require_once('include/security.php');
|
|
||||||
change_channel($r[0]['channel_id']);
|
|
||||||
$delegation_success = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
logger('mod_zot: magic-auth failure - not authenticated: ' . $xx['xchan_addr']);
|
||||||
|
q("update hubloc set hubloc_status = (hubloc_status | %d ) where hubloc_id = %d ",
|
||||||
|
intval(HUBLOC_RECEIVE_ERROR),
|
||||||
|
intval($xx['hubloc_id'])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['authenticated'] = 1;
|
|
||||||
if (! $delegation_success) {
|
|
||||||
$_SESSION['visitor_id'] = $x[0]['xchan_hash'];
|
|
||||||
$_SESSION['my_url'] = $x[0]['xchan_url'];
|
|
||||||
$_SESSION['my_address'] = $address;
|
|
||||||
$_SESSION['remote_service_class'] = $remote_service_class;
|
|
||||||
$_SESSION['remote_level'] = $remote_level;
|
|
||||||
$_SESSION['remote_hub'] = $remote_hub;
|
|
||||||
$_SESSION['DNT'] = $DNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
$arr = array('xchan' => $x[0], 'url' => $desturl, 'session' => $_SESSION);
|
|
||||||
call_hooks('magic_auth_success',$arr);
|
|
||||||
$a->set_observer($x[0]);
|
|
||||||
require_once('include/security.php');
|
|
||||||
$a->set_groups(init_groups_visitor($_SESSION['visitor_id']));
|
|
||||||
info(sprintf( t('Welcome %s. Remote authentication successful.'),$x[0]['xchan_name']));
|
|
||||||
logger('mod_zot: auth success from ' . $x[0]['xchan_addr']);
|
|
||||||
q("update hubloc set hubloc_status = (hubloc_status | %d ) where hubloc_id = %d ",
|
|
||||||
intval(HUBLOC_WORKS),
|
|
||||||
intval($x[0]['hubloc_id'])
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if ($test) {
|
if ($test) {
|
||||||
$ret['message'] .= 'auth failure. ' . print_r($_REQUEST,true) . print_r($j,true) . EOL;
|
$ret['message'] .= 'auth failure fallthrough ' . print_r($_REQUEST,true) . print_r($j,true) . EOL;
|
||||||
json_return_and_die($ret);
|
continue;
|
||||||
}
|
}
|
||||||
logger('mod_zot: magic-auth failure - not authenticated: ' . $x[0]['xchan_addr']);
|
|
||||||
q("update hubloc set hubloc_status = (hubloc_status | %d ) where hubloc_id = %d ",
|
|
||||||
intval(HUBLOC_RECEIVE_ERROR),
|
|
||||||
intval($x[0]['hubloc_id'])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @FIXME we really want to save the return_url in the session before we
|
* @FIXME we really want to save the return_url in the session before we
|
||||||
* visit rmagic. This does however prevent a recursion if you visit
|
* visit rmagic. This does however prevent a recursion if you visit
|
||||||
@ -308,14 +316,13 @@ function post_init(&$a) {
|
|||||||
* But z_root() probably isn't where you really want to go.
|
* But z_root() probably isn't where you really want to go.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ($test) {
|
|
||||||
$ret['message'] .= 'auth failure fallthrough ' . print_r($_REQUEST,true) . print_r($j,true) . EOL;
|
|
||||||
json_return_and_die($ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strstr($desturl,z_root() . '/rmagic'))
|
if(strstr($desturl,z_root() . '/rmagic'))
|
||||||
goaway(z_root());
|
goaway(z_root());
|
||||||
|
|
||||||
|
if ($test) {
|
||||||
|
json_return_and_die($ret);
|
||||||
|
}
|
||||||
|
|
||||||
goaway($desturl);
|
goaway($desturl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
2015-09-20.1161
|
2015-09-21.1162
|
||||||
|
Reference in New Issue
Block a user