X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=actions%2Fuserauthorization.php;h=680f55094c7916da8a8aca6576056ba80bfe4577;hb=b3ed4e5e20523673d4005415e8d9f26bf0748659;hp=eb93b6fd301d06a77e3beb8b9bac16eb328a5949;hpb=5fb2072bc9158373f079a5e8997d195d0220e038;p=quix0rs-gnu-social.git diff --git a/actions/userauthorization.php b/actions/userauthorization.php index eb93b6fd30..680f55094c 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -23,42 +23,49 @@ require_once(INSTALLDIR.'/lib/omb.php'); define('TIMESTAMP_THRESHOLD', 300); class UserauthorizationAction extends Action { + function handle($args) { parent::handle($args); - + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + # CSRF protection + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $req = $this->get_stored_request(); + $this->show_form(_('There was a problem with your session token. Try again, please.'), $req); + return; + } # We've shown the form, now post user's choice $this->send_authorization(); } else { if (!common_logged_in()) { # Go log in, and then come back - common_debug('userauthorization.php - saving URL for returnto'); - $argsclone = $_GET; - unset($argsclone['action']); - common_set_returnto(common_local_url('userauthorization', $argsclone)); - common_debug('userauthorization.php - redirecting to login'); + common_debug('saving URL for returnto', __FILE__); + common_set_returnto($_SERVER['REQUEST_URI']); + + common_debug('redirecting to login', __FILE__); common_redirect(common_local_url('login')); return; } try { # this must be a new request - common_debug('userauthorization.php - getting new request'); + common_debug('getting new request', __FILE__); $req = $this->get_new_request(); if (!$req) { - common_server_error(_t('No request found!')); + $this->client_error(_('No request found!')); } - common_debug('userauthorization.php - validating request'); + common_debug('validating request', __FILE__); # XXX: only validate new requests, since nonce is one-time use $this->validate_request($req); - common_debug('userauthorization.php - showing form'); + common_debug('showing form', __FILE__); $this->store_request($req); $this->show_form($req); } catch (OAuthException $e) { $this->clear_request(); - common_server_error($e->getMessage()); + $this->client_error($e->getMessage()); return; } - + } } @@ -72,12 +79,12 @@ class UserauthorizationAction extends Action { $bio = $req->get_parameter('omb_listenee_bio'); $location = $req->get_parameter('omb_listenee_location'); $avatar = $req->get_parameter('omb_listenee_avatar'); - - common_show_header(_t('Authorize subscription')); - common_element('p', _t('Please check these details to make sure '. - 'that you want to subscribe to this user\'s notices. '. - 'If you didn\'t just ask to subscribe to someone\'s notices, '. - 'click "Cancel".')); + + common_show_header(_('Authorize subscription')); + common_element('p', NULL, _('Please check these details to make sure '. + 'that you want to subscribe to this user\'s notices. '. + 'If you didn\'t just ask to subscribe to someone\'s notices, '. + 'click "Cancel".')); common_element_start('div', 'profile'); if ($avatar) { common_element('img', array('src' => $avatar, @@ -111,29 +118,34 @@ class UserauthorizationAction extends Action { $license); common_element_end('div'); common_element_end('div'); - common_element_start('form', array('method' => 'POST', + common_element_start('form', array('method' => 'post', 'id' => 'userauthorization', 'name' => 'userauthorization', 'action' => common_local_url('userauthorization'))); - common_submit('accept', _t('Accept')); - common_submit('reject', _t('Reject')); + common_hidden('token', common_session_token()); + common_submit('accept', _('Accept')); + common_submit('reject', _('Reject')); common_element_end('form'); common_show_footer(); } - + function send_authorization() { $req = $this->get_stored_request(); - + if (!$req) { - common_user_error(_t('No authorization request!')); + common_user_error(_('No authorization request!')); return; } $callback = $req->get_parameter('oauth_callback'); if ($this->arg('accept')) { - $this->authorize_token($req); - $this->save_remote_profile($req); + if (!$this->authorize_token($req)) { + $this->client_error(_('Error authorizing token')); + } + if (!$this->save_remote_profile($req)) { + $this->client_error(_('Error saving remote profile')); + } if (!$callback) { $this->show_accept_message($req->get_parameter('oauth_token')); } else { @@ -142,6 +154,11 @@ class UserauthorizationAction extends Action { $params['omb_version'] = OMB_VERSION_01; $user = User::staticGet('uri', $req->get_parameter('omb_listener')); $profile = $user->getProfile(); + if (!$profile) { + common_log_db_error($user, 'SELECT', __FILE__); + $this->server_error(_('User without matching profile')); + return; + } $params['omb_listener_nickname'] = $user->nickname; $params['omb_listener_profile'] = common_local_url('showstream', array('nickname' => $user->nickname)); @@ -181,15 +198,22 @@ class UserauthorizationAction extends Action { } function authorize_token(&$req) { - $consumer_key = @$req->get_parameter('oauth_consumer_key'); - $token_field = @$req->get_parameter('oauth_token'); + $consumer_key = $req->get_parameter('oauth_consumer_key'); + $token_field = $req->get_parameter('oauth_token'); + common_debug('consumer key = "'.$consumer_key.'"', __FILE__); + common_debug('token field = "'.$token_field.'"', __FILE__); $rt = new Token(); $rt->consumer_key = $consumer_key; $rt->tok = $token_field; - if ($rt->find(TRUE)) { + $rt->type = 0; + $rt->state = 0; + common_debug('request token to look up: "'.print_r($rt,TRUE).'"'); + if ($rt->find(true)) { + common_debug('found request token to authorize', __FILE__); $orig_rt = clone($rt); $rt->state = 1; # Authorized but not used if ($rt->update($orig_rt)) { + common_debug('updated request token so it is authorized', __FILE__); return true; } } @@ -197,23 +221,23 @@ class UserauthorizationAction extends Action { } # XXX: refactor with similar code in finishremotesubscribe.php - + function save_remote_profile(&$req) { # FIXME: we should really do this when the consumer comes - # back for an access token. If they never do, we've got stuff in a + # back for an access token. If they never do, we've got stuff in a # weird state. - + $nickname = $req->get_parameter('omb_listenee_nickname'); $fullname = $req->get_parameter('omb_listenee_fullname'); - $profile_url = $req->get_parameter('omb_listenee_profile'); + $profile_url = $req->get_parameter('omb_listenee_profile'); $homepage = $req->get_parameter('omb_listenee_homepage'); $bio = $req->get_parameter('omb_listenee_bio'); $location = $req->get_parameter('omb_listenee_location'); $avatar_url = $req->get_parameter('omb_listenee_avatar'); - + $listenee = $req->get_parameter('omb_listenee'); $remote = Remote_profile::staticGet('uri', $listenee); - + if ($remote) { $exists = true; $profile = Profile::staticGet($remote->id); @@ -228,7 +252,7 @@ class UserauthorizationAction extends Action { $profile->nickname = $nickname; $profile->profileurl = $profile_url; - + if ($fullname) { $profile->fullname = $fullname; } @@ -241,24 +265,33 @@ class UserauthorizationAction extends Action { if ($location) { $profile->location = $location; } - + if ($exists) { $profile->update($orig_profile); } else { $profile->created = DB_DataObject_Cast::dateTime(); # current time $id = $profile->insert(); + if (!$id) { + return FALSE; + } $remote->id = $id; } if ($exists) { - $remote->update($orig_remote); + if (!$remote->update($orig_remote)) { + return FALSE; + } } else { $remote->created = DB_DataObject_Cast::dateTime(); # current time - $remote->insert(); + if (!$remote->insert()) { + return FALSE; + } } if ($avatar_url) { - $this->add_avatar($profile, $avatar_url); + if (!$this->add_avatar($profile, $avatar_url)) { + return FALSE; + } } $user = common_current_user(); @@ -271,11 +304,12 @@ class UserauthorizationAction extends Action { $sub->subscribed = $remote->id; $sub->token = $token->key; # NOTE: request token, not valid for use! $sub->created = DB_DataObject_Cast::dateTime(); # current time - + if (!$sub->insert()) { - common_user_error(_t('Couldn\'t insert new subscription.')); - return; + return FALSE; } + + return TRUE; } function add_avatar($profile, $url) { @@ -283,11 +317,11 @@ class UserauthorizationAction extends Action { copy($url, $temp_filename); return $profile->setOriginal($temp_filename); } - + function show_accept_message($tok) { - common_show_header(_t('Subscription authorized')); - common_element('p', NULL, - _t('The subscription has been authorized, but no '. + common_show_header(_('Subscription authorized')); + common_element('p', NULL, + _('The subscription has been authorized, but no '. 'callback URL was passed. Check with the site\'s instructions for '. 'details on how to authorize the subscription. Your subscription token is:')); common_element('blockquote', 'token', $tok); @@ -295,57 +329,58 @@ class UserauthorizationAction extends Action { } function show_reject_message($tok) { - common_show_header(_t('Subscription rejected')); - common_element('p', NULL, - _t('The subscription has been rejected, but no '. + common_show_header(_('Subscription rejected')); + common_element('p', NULL, + _('The subscription has been rejected, but no '. 'callback URL was passed. Check with the site\'s instructions for '. 'details on how to fully reject the subscription.')); common_show_footer(); } - + function store_request($req) { common_ensure_session(); $_SESSION['userauthorizationrequest'] = $req; } - + function clear_request() { common_ensure_session(); unset($_SESSION['userauthorizationrequest']); } - + function get_stored_request() { - common_ensure_session(); + common_ensure_session(); $req = $_SESSION['userauthorizationrequest']; return $req; } function get_new_request() { + common_remove_magic_from_request(); $req = OAuthRequest::from_request(); return $req; } - + # Throws an OAuthException if anything goes wrong - + function validate_request(&$req) { # OAuth stuff -- have to copy from OAuth.php since they're # all private methods, and there's no user-authentication method common_debug('checking version', __FILE__); $this->check_version($req); - common_debug('getting datastore', __FILE__); + common_debug('getting datastore', __FILE__); $datastore = omb_oauth_datastore(); common_debug('getting consumer', __FILE__); $consumer = $this->get_consumer($datastore, $req); - common_debug('getting token', __FILE__); + common_debug('getting token', __FILE__); $token = $this->get_token($datastore, $req, $consumer); common_debug('checking timestamp', __FILE__); $this->check_timestamp($req); - common_debug('checking nonce', __FILE__); + common_debug('checking nonce', __FILE__); $this->check_nonce($datastore, $req, $consumer, $token); common_debug('checking signature', __FILE__); $this->check_signature($req, $consumer, $token); - common_debug('validating omb stuff', __FILE__); + common_debug('validating omb stuff', __FILE__); $this->validate_omb($req); - common_debug('done validating', __FILE__); + common_debug('done validating', __FILE__); return true; } @@ -363,10 +398,15 @@ class UserauthorizationAction extends Action { if ($version != OMB_VERSION_01) { throw new OAuthException("OpenMicroBlogging version '$version' not supported"); } - $user = User::staticGet('uri', $req->get_parameter('omb_listener')); + $listener = $req->get_parameter('omb_listener'); + $user = User::staticGet('uri', $listener); if (!$user) { throw new OAuthException("Listener URI '$listener' not found here"); } + $cur = common_current_user(); + if ($cur->id != $user->id) { + throw new OAuthException("Can't add for another user!"); + } $listenee = $req->get_parameter('omb_listenee'); if (!Validate::uri($listenee) && !common_valid_tag($listenee)) { @@ -375,6 +415,15 @@ class UserauthorizationAction extends Action { if (strlen($listenee) > 255) { throw new OAuthException("Listenee URI '$listenee' too long"); } + $remote = Remote_profile::staticGet('uri', $listenee); + if ($remote) { + $sub = new Subscription(); + $sub->subscriber = $user->id; + $sub->subscribed = $remote->id; + if ($sub->find(TRUE)) { + throw new OAuthException("Already subscribed to user!"); + } + } $nickname = $req->get_parameter('omb_listenee_nickname'); if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, @@ -428,9 +477,9 @@ class UserauthorizationAction extends Action { throw new OAuthException("Invalid callback URL '$callback'"); } } - + # Snagged from OAuthServer - + function check_version(&$req) { $version = $req->get_parameter("oauth_version"); if (!$version) { @@ -443,13 +492,13 @@ class UserauthorizationAction extends Action { } # Snagged from OAuthServer - + function get_consumer($datastore, $req) { $consumer_key = @$req->get_parameter("oauth_consumer_key"); if (!$consumer_key) { throw new OAuthException("Invalid consumer key"); } - + $consumer = $datastore->lookup_consumer($consumer_key); if (!$consumer) { throw new OAuthException("Invalid consumer"); @@ -458,7 +507,7 @@ class UserauthorizationAction extends Action { } # Mostly cadged from OAuthServer - + function get_token($datastore, &$req, $consumer) {/*{{{*/ $token_field = @$req->get_parameter('oauth_token'); $token = $datastore->lookup_token($consumer, 'request', $token_field); @@ -467,7 +516,7 @@ class UserauthorizationAction extends Action { } return $token; } - + function check_timestamp(&$req) { $timestamp = @$req->get_parameter('oauth_timestamp'); $now = time(); @@ -486,19 +535,19 @@ class UserauthorizationAction extends Action { } return true; } - + function check_signature(&$req, $consumer, $token) { $signature_method = $this->get_signature_method($req); - $signature = $req->get_parameter('oauth_signature'); - $valid_sig = $signature_method->check_signature($req, - $consumer, - $token, + $signature = $req->get_parameter('oauth_signature'); + $valid_sig = $signature_method->check_signature($req, + $consumer, + $token, $signature); if (!$valid_sig) { throw new OAuthException("Invalid signature"); } } - + function get_signature_method(&$req) { $signature_method = @$req->get_parameter("oauth_signature_method"); if (!$signature_method) {