1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

CSRF / Logout

This commit is contained in:
epriestley 2011-01-30 18:52:29 -08:00
parent 58d1506499
commit 29f7219a49
26 changed files with 152 additions and 7 deletions

View file

@ -137,6 +137,7 @@ phutil_register_library_map(array(
'PhabricatorFileViewController' => 'applications/files/controller/view',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorLoginController' => 'applications/auth/controlller/login',
'PhabricatorLogoutController' => 'applications/auth/controlller/logout',
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
@ -290,6 +291,7 @@ phutil_register_library_map(array(
'PhabricatorFileViewController' => 'PhabricatorFileController',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorLoginController' => 'PhabricatorAuthController',
'PhabricatorLogoutController' => 'PhabricatorAuthController',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',

View file

@ -116,6 +116,7 @@ class AphrontDefaultApplicationConfiguration
),
'/login/' => 'PhabricatorLoginController',
'/logout/' => 'PhabricatorLogoutController',
);
}

View file

@ -86,7 +86,9 @@ class AphrontRequest {
}
final public function isFormPost() {
return $this->getExists(self::TYPE_FORM) && $this->isHTTPPost();
return $this->getExists(self::TYPE_FORM) &&
$this->isHTTPPost() &&
$this->getUser()->validateCSRFToken($this->getStr('__csrf__'));
}
final public function getCookie($name, $default = null) {

View file

@ -26,7 +26,7 @@ class PhabricatorLoginController extends PhabricatorAuthController {
$request = $this->getRequest();
$error = false;
$login_name = $request->getCookie('phu');
$login_name = $request->getCookie('phusr');
if ($request->isFormPost()) {
$login_name = $request->getStr('login');
@ -89,6 +89,7 @@ class PhabricatorLoginController extends PhabricatorAuthController {
$form = new AphrontFormView();
$form
->setUser($request->getUser())
->setAction('/login/')
->appendChild(
id(new AphrontFormTextControl())

View file

@ -0,0 +1,37 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorLogoutController extends PhabricatorAuthController {
public function shouldRequireLogin() {
return true;
}
public function processRequest() {
$request = $this->getRequest();
if ($request->isFormPost()) {
$request->clearCookie('phsid');
return id(new AphrontRedirectResponse())
->setURI('/login/');
}
return id(new AphrontRedirectResponse())->setURI('/');
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/auth/controlller/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorLogoutController.php');

View file

@ -26,6 +26,9 @@ class PhabricatorConduitConsoleController
}
public function processRequest() {
$request = $this->getRequest();
$methods = $this->getAllMethods();
if (empty($methods[$this->method])) {
$this->method = key($methods);
@ -55,6 +58,7 @@ class PhabricatorConduitConsoleController
$form = new AphrontFormView();
$form
->setUser($request->getUser())
->setAction('/api/'.$this->method)
->appendChild(
id(new AphrontFormStaticControl())

View file

@ -25,6 +25,8 @@ class DifferentialDiffViewController extends DifferentialController {
}
public function processRequest() {
$request = $this->getRequest();
$diff = id(new DifferentialDiff())->load($this->id);
if (!$diff) {
return new Aphront404Response();
@ -40,6 +42,7 @@ class DifferentialDiffViewController extends DifferentialController {
$action_form = new AphrontFormView();
$action_form
->setUser($request->getUser())
->setAction('/differential/revision/edit/')
->addHiddenInput('diffID', $diff->getID())
->addHiddenInput('viaDiffView', 1)

View file

@ -100,6 +100,7 @@ class DifferentialRevisionEditController extends DifferentialController {
}
$form = new AphrontFormView();
$form->setUser($request->getUser());
if ($diff) {
$form->addHiddenInput('diffID', $diff->getID());
}

View file

@ -84,6 +84,7 @@ class DifferentialRevisionViewController extends DifferentialController {
$comment_form->setRevision($revision);
$comment_form->setActions($this->getRevisionCommentActions($revision));
$comment_form->setActionURI('/differential/comment/save/');
$comment_form->setUser($request->getUser());
return $this->buildStandardPageResponse(
'<div class="differential-primary-pane">'.

View file

@ -21,6 +21,7 @@ final class DifferentialAddCommentView extends AphrontView {
private $revision;
private $actions;
private $actionURI;
private $user;
public function setRevision($revision) {
$this->revision = $revision;
@ -36,8 +37,11 @@ final class DifferentialAddCommentView extends AphrontView {
$this->actionURI = $uri;
}
public function render() {
public function setUser(PhabricatorUser $user) {
$this->user = $user;
}
public function render() {
$revision = $this->revision;
$actions = array();
@ -47,6 +51,7 @@ final class DifferentialAddCommentView extends AphrontView {
$form = new AphrontFormView();
$form
->setUser($this->user)
->setAction($this->actionURI)
->addHiddenInput('revision_id', $revision->getID())
->appendChild(

View file

@ -64,6 +64,7 @@ class PhabricatorDirectoryCategoryEditController
}
$form = new AphrontFormView();
$form->setUser($request->getUser());
if ($category->getID()) {
$form->setAction('/directory/category/edit/'.$category->getID().'/');
} else {

View file

@ -73,6 +73,8 @@ class PhabricatorDirectoryItemEditController
}
$form = new AphrontFormView();
$form->setUser($request->getUser());
if ($item->getID()) {
$form->setAction('/directory/item/edit/'.$item->getID().'/');
} else {

View file

@ -34,6 +34,7 @@ class PhabricatorFileUploadController extends PhabricatorFileController {
$form = new AphrontFormView();
$form->setAction('/file/upload/');
$form->setUser($request->getUser());
$form
->setEncType('multipart/form-data')

View file

@ -65,6 +65,7 @@ class PhabricatorMetaMTAMailingListEditController
}
$form = new AphrontFormView();
$form->setUser($request->getUser());
if ($list->getID()) {
$form->setAction('/mail/lists/edit/'.$list->getID().'/');
} else {

View file

@ -49,6 +49,7 @@ class PhabricatorMetaMTASendController extends PhabricatorMetaMTAController {
$form = new AphrontFormView();
$form->setUser($request->getUser());
$form->setAction('/mail/send/');
$form
->appendChild(

View file

@ -26,14 +26,17 @@ class PhabricatorMetaMTAViewController extends PhabricatorMetaMTAController {
public function processRequest() {
$request = $this->getRequest();
$mail = id(new PhabricatorMetaMTAMail())->load($this->id);
if (!$mail) {
return new Aphront404Response();
}
$status = PhabricatorMetaMTAMail::getReadableStatus($mail->getStatus());
$form = new AphrontFormView();
$form->setUser($request->getUser());
$form->setAction('/mail/send/');
$form
->appendChild(

View file

@ -84,6 +84,7 @@ class PhabricatorPeopleEditController extends PhabricatorPeopleController {
}
$form = new AphrontFormView();
$form->setUser($request->getUser());
if ($user->getUsername()) {
$form->setAction('/people/edit/'.$user->getUsername().'/');
} else {

View file

@ -27,6 +27,8 @@ class PhabricatorUser extends PhabricatorUserDAO {
protected $passwordSalt;
protected $passwordHash;
private $sessionKey;
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
@ -60,4 +62,29 @@ class PhabricatorUser extends PhabricatorUserDAO {
return $password;
}
const CSRF_CYCLE_FREQUENCY = 3600;
public function getCSRFToken() {
return $this->generateCSRFToken(time());
}
public function validateCSRFToken($token) {
for ($ii = -1; $ii <= 1; $ii++) {
$time = time() + (self::CSRF_CYCLE_FREQUENCY * $ii);
$valid = $this->generateCSRFToken($time);
if ($token == $valid) {
return true;
}
}
return false;
}
private function generateCSRFToken($epoch) {
$time_block = floor($epoch / (60 * 60));
// TODO: this should be a secret lolol
$key = '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3';
$vec = $this->getPHID().$this->passwordHash.$key.$time_block;
return substr(md5($vec), 0, 16);
}
}

View file

@ -31,7 +31,7 @@ class PhabricatorPHIDAllocateController
}
$types = id(new PhabricatorPHIDType())->loadAll();
$options = array();
foreach ($types as $type) {
$options[$type->getType()] = $type->getType().': '.$type->getName();
@ -39,6 +39,7 @@ class PhabricatorPHIDAllocateController
asort($options);
$form = new AphrontFormView();
$form->setUser($request->getUser());
$form->setAction('/phid/new/');
$form

View file

@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');

View file

@ -82,6 +82,7 @@ class PhabricatorPHIDLookupController
}
$lookup_form = new AphrontFormView();
$lookup_form->setUser($request->getUser());
$lookup_form
->setAction('/phid/')
->appendChild(

View file

@ -73,6 +73,8 @@ class PhabricatorPHIDTypeEditController
}
$form = new AphrontFormView();
$form->setUser($request->getUser());
if ($type->getID()) {
$form->setAction('/phid/type/edit/'.$type->getID().'/');
} else {
@ -85,6 +87,7 @@ class PhabricatorPHIDTypeEditController
$type_immutable = false;
}
$form
->appendChild(
id(new AphrontFormTextControl())

View file

@ -23,6 +23,12 @@ final class AphrontFormView extends AphrontView {
private $header;
private $data = array();
private $encType;
private $user;
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
public function setAction($action) {
$this->action = $action;
@ -59,8 +65,13 @@ final class AphrontFormView extends AphrontView {
}
private function renderDataInputs() {
if (!$this->user) {
throw new Exception('You must pass the user to AphrontFormView.');
}
$data = $this->data + array(
'__form__' => 1,
'__csrf__' => $this->user->getCSRFToken(),
);
$inputs = array();
foreach ($data as $key => $value) {

View file

@ -117,7 +117,26 @@ class PhabricatorStandardPageView extends AphrontPageView {
if ($request) {
$user = $request->getUser();
if ($user->getPHID()) {
$login_stuff = 'Logged in as '.phutil_escape_html($user->getUsername());
$login_stuff =
'Logged in as '.phutil_escape_html($user->getUsername()).
' &middot; '.
'<form action="/logout/" method="post" style="display: inline;">'.
phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => '__csrf__',
'value' => $user->getCSRFToken(),
)).
phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => '__form__',
'value' => true,
)).
'<button class="small grey">Logout</button>'.
'</form>';
}
}

View file

@ -26,7 +26,7 @@ function phabricator_format_relative_time($duration) {
function phabricator_format_timestamp($epoch) {
$difference = (time() - $epoch);
if ($difference < 60 * 60) {
return phabricator_format_relative_time($difference).' ago';
} else if (date('Y') == date('Y', $epoch)) {