]> source.dussan.org Git - nextcloud-server.git/commitdiff
Create only one CSRF token per session
authorLukas Reschke <lukas@statuscode.ch>
Wed, 31 Oct 2012 17:37:59 +0000 (18:37 +0100)
committerLukas Reschke <lukas@statuscode.ch>
Wed, 31 Oct 2012 17:37:59 +0000 (18:37 +0100)
Before, the CSRF token expired every hour. We had a script in place
which should refresh the token but this don't worked in every case.
(Laptop sleeping etc.)

With this commit, the token will only get once created for every
session so that the "Token expired" warning shouldn't appear.

core/ajax/requesttoken.php [deleted file]
core/js/requesttoken.js [deleted file]
core/routes.php
core/templates/layout.base.php
core/templates/layout.guest.php
core/templates/layout.user.php
lib/base.php
lib/template.php
lib/util.php

diff --git a/core/ajax/requesttoken.php b/core/ajax/requesttoken.php
deleted file mode 100644 (file)
index 9d43a72..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
-* ownCloud
-* @author Christian Reiner
-* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the license, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library.
-* If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * @file core/ajax/requesttoken.php
- * @brief Ajax method to retrieve a fresh request protection token for ajax calls
- * @return json: success/error state indicator including a fresh request token
- * @author Christian Reiner
- */
-
-// don't load apps or filesystem for this task
-$RUNTIME_NOAPPS    = true;
-$RUNTIME_NOSETUPFS = true;
-
-// Sanity checks
-// using OCP\JSON::callCheck() below protects the token refreshing itself.
-//OCP\JSON::callCheck ( );
-OCP\JSON::checkLoggedIn ( );
-// hand out a fresh token
-OCP\JSON::success ( array ( 'token'   => OCP\Util::callRegister() ) );
-?>
diff --git a/core/js/requesttoken.js b/core/js/requesttoken.js
deleted file mode 100644 (file)
index 0d78cd7..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * ownCloud
- *
- * @file core/js/requesttoken.js
- * @brief Routine to refresh the Request protection request token periodically
- * @author Christian Reiner (arkascha)
- * @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the license, or any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.
- * If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-OC.Request = {
-       // the request token
-       Token: {},
-       // the lifespan span (in secs)
-       Lifespan: {},
-       // method to refresh the local request token periodically
-       Refresh: function(){
-               // just a client side console log to preserve efficiency
-               console.log("refreshing request token (lifebeat)");
-               var dfd=new $.Deferred();
-               $.ajax({
-                       type:     'POST',
-                       url:      OC.filePath('core','ajax','requesttoken.php'),
-                       cache:    false,
-                       data:     { },
-                       dataType: 'json'
-               }).done(function(response){
-                       // store refreshed token inside this class
-                       OC.Request.Token=response.token;
-                       dfd.resolve();
-               }).fail(dfd.reject);
-               return dfd;
-       }
-}
-// accept requesttoken and lifespan into the OC namespace
-OC.Request.Token = oc_requesttoken;
-OC.Request.Lifespan = oc_requestlifespan;
-// refresh the request token periodically shortly before it becomes invalid on the server side
-setInterval(OC.Request.Refresh,Math.floor(1000*OC.Request.Lifespan*0.93)), // 93% of lifespan value, close to when the token expires
-// early bind token as additional ajax argument for every single request
-$(document).bind('ajaxSend', function(elm, xhr, s){xhr.setRequestHeader('requesttoken', OC.Request.Token);});
index cc0aa53a21e6b3f071655e3887a144dc33cd1774..6f9993566890a9d95098186edb6cd39385f57e76 100644 (file)
@@ -13,9 +13,6 @@ $this->create('search_ajax_search', '/search/ajax/search.php')
 // AppConfig
 $this->create('core_ajax_appconfig', '/core/ajax/appconfig.php')
        ->actionInclude('core/ajax/appconfig.php');
-// RequestToken
-$this->create('core_ajax_requesttoken', '/core/ajax/requesttoken.php')
-       ->actionInclude('core/ajax/requesttoken.php');
 // Share
 $this->create('core_ajax_share', '/core/ajax/share.php')
        ->actionInclude('core/ajax/share.php');
index f78b6ff8bbd47eb0f815d771eb3264900b0a295c..d8f830587759dbbbc03a2ccc5e641033df21af9c 100644 (file)
@@ -11,7 +11,6 @@
                        var oc_webroot = '<?php echo OC::$WEBROOT; ?>';
                        var oc_appswebroots = <?php echo $_['apps_paths'] ?>;
                        var oc_requesttoken = '<?php echo $_['requesttoken']; ?>';
-                       var oc_requestlifespan = '<?php echo $_['requestlifespan']; ?>';
                </script>
                <?php foreach ($_['jsfiles'] as $jsfile): ?>
                        <script type="text/javascript" src="<?php echo $jsfile; ?>"></script>
index e6468cdcfb4ee62dc511d9ba78edcb77830b11cc..2eaa517b3244160edc726427e06292988aab2d1f 100644 (file)
@@ -11,7 +11,6 @@
                        var oc_webroot = '<?php echo OC::$WEBROOT; ?>';
                        var oc_appswebroots = <?php echo $_['apps_paths'] ?>;
                        var oc_requesttoken = '<?php echo $_['requesttoken']; ?>';
-                       var oc_requestlifespan = '<?php echo $_['requestlifespan']; ?>';
                        var datepickerFormatDate = <?php echo json_encode($l->l('jsdate', 'jsdate')) ?>;
                        var dayNames = <?php echo json_encode(array((string)$l->t('Sunday'), (string)$l->t('Monday'), (string)$l->t('Tuesday'), (string)$l->t('Wednesday'), (string)$l->t('Thursday'), (string)$l->t('Friday'), (string)$l->t('Saturday'))) ?>;
                        var monthNames = <?php echo json_encode(array((string)$l->t('January'), (string)$l->t('February'), (string)$l->t('March'), (string)$l->t('April'), (string)$l->t('May'), (string)$l->t('June'), (string)$l->t('July'), (string)$l->t('August'), (string)$l->t('September'), (string)$l->t('October'), (string)$l->t('November'), (string)$l->t('December'))) ?>;
index d876fbc98e8d9ac16cc2fc04248ac0c7e71b5fb6..451a4685e826060d6e743576263a969b480bc6d1 100644 (file)
@@ -12,7 +12,6 @@
                        var oc_appswebroots = <?php echo $_['apps_paths'] ?>;
                        var oc_current_user = '<?php echo OC_User::getUser() ?>';
                        var oc_requesttoken = '<?php echo $_['requesttoken']; ?>';
-                       var oc_requestlifespan = '<?php echo $_['requestlifespan']; ?>';
                        var datepickerFormatDate = <?php echo json_encode($l->l('jsdate', 'jsdate')) ?>;
                        var dayNames = <?php echo json_encode(array((string)$l->t('Sunday'), (string)$l->t('Monday'), (string)$l->t('Tuesday'), (string)$l->t('Wednesday'), (string)$l->t('Thursday'), (string)$l->t('Friday'), (string)$l->t('Saturday'))) ?>;
                        var monthNames = <?php echo json_encode(array((string)$l->t('January'), (string)$l->t('February'), (string)$l->t('March'), (string)$l->t('April'), (string)$l->t('May'), (string)$l->t('June'), (string)$l->t('July'), (string)$l->t('August'), (string)$l->t('September'), (string)$l->t('October'), (string)$l->t('November'), (string)$l->t('December'))) ?>;
                <?php foreach($_['jsfiles'] as $jsfile): ?>
                        <script type="text/javascript" src="<?php echo $jsfile; ?>"></script>
                <?php endforeach; ?>
+               <script type="text/javascript">
+                       requesttoken = '<?php echo $_['requesttoken']; ?>';
+                       OC.EventSource.requesttoken=requesttoken;
+                       $(document).bind('ajaxSend', function(elm, xhr, s) {
+                               xhr.setRequestHeader('requesttoken', requesttoken);
+                       });
+               </script>
                <?php foreach($_['headers'] as $header): ?>
                        <?php
                                echo '<'.$header['tag'].' ';
index d7d5eef32564e04c1ad4a92ff113bd1640382826..87fb1644240670d2956c5a4c5af7986e78479e44 100644 (file)
@@ -254,8 +254,6 @@ class OC{
                OC_Util::addScript( "jquery-tipsy" );
                OC_Util::addScript( "oc-dialogs" );
                OC_Util::addScript( "js" );
-               // request protection token MUST be defined after the jquery library but before any $('document').ready()
-               OC_Util::addScript( "requesttoken" );
                OC_Util::addScript( "eventsource" );
                OC_Util::addScript( "config" );
                //OC_Util::addScript( "multiselect" );
index 1ad47cbe52cdf9050e66d1e5b41193d8885f111a..caac6891cb834992fd0015d1157ff4d9385badaf 100644 (file)
@@ -172,7 +172,6 @@ class OC_Template{
                $this->application = $app;
                $this->vars = array();
                $this->vars['requesttoken'] = OC_Util::callRegister();
-               $this->vars['requestlifespan'] = OC_Util::$callLifespan;
                $parts = explode('/', $app); // fix translation when app is something like core/lostpassword
                $this->l10n = OC_L10N::get($parts[0]);
 
@@ -391,7 +390,6 @@ class OC_Template{
                        $page = new OC_TemplateLayout($this->renderas);
                        if($this->renderas == 'user') {
                                $page->assign('requesttoken', $this->vars['requesttoken']);
-                               $page->assign('requestlifespan', $this->vars['requestlifespan']);
                        }
 
                        // Add custom headers
index de89e339d99ef5d6c17fe9fa9ed70e322b19114e..cb81f0a948ce6ea798a4aba94de895b078614a6d 100755 (executable)
@@ -472,17 +472,6 @@ class OC_Util {
                return $id;
        }
 
-       /**
-        * @brief Static lifespan (in seconds) when a request token expires.
-        * @see OC_Util::callRegister()
-        * @see OC_Util::isCallRegistered()
-        * @description
-        * Also required for the client side to compute the piont in time when to
-        * request a fresh token. The client will do so when nearly 97% of the
-        * timespan coded here has expired.
-        */
-       public static $callLifespan = 3600; // 3600 secs = 1 hour
-
        /**
         * @brief Register an get/post call. Important to prevent CSRF attacks.
         * @todo Write howto: CSRF protection guide
@@ -491,30 +480,24 @@ class OC_Util {
         * Creates a 'request token' (random) and stores it inside the session.
         * Ever subsequent (ajax) request must use such a valid token to succeed,
         * otherwise the request will be denied as a protection against CSRF.
-        * The tokens expire after a fixed lifespan.
-        * @see OC_Util::$callLifespan
         * @see OC_Util::isCallRegistered()
         */
        public static function callRegister() {
                // Check if a token exists
-               if(!isset($_SESSION['requesttoken']) || time() >$_SESSION['requesttoken']['time']) {
+               if(!isset($_SESSION['requesttoken'])) {
                        // No valid token found, generate a new one.
-                       $requestTokenArray = array(
-                               "requesttoken" => self::generate_random_bytes(20),
-                               "time" => time()+self::$callLifespan,
-                               );
-                       $_SESSION['requesttoken']=$requestTokenArray;
+                       $requestToken = self::generate_random_bytes(20);
+                       $_SESSION['requesttoken']=$requestToken;
                } else {
                        // Valid token already exists, send it
-                       $requestTokenArray = $_SESSION['requesttoken'];
+                       $requestToken = $_SESSION['requesttoken'];
                }
-               return($requestTokenArray['requesttoken']);
+               return($requestToken);
        }
 
        /**
         * @brief Check an ajax get/post call if the request token is valid.
         * @return boolean False if request token is not set or is invalid.
-        * @see OC_Util::$callLifespan
         * @see OC_Util::callRegister()
         */
        public static function isCallRegistered() {
@@ -530,7 +513,7 @@ class OC_Util {
                }
 
                // Check if the token is valid
-               if(!isset($_SESSION['requesttoken']) || time() > $_SESSION['requesttoken']["time"]) {
+               if($token !== $_SESSION['requesttoken']) {
                        // Not valid
                        return false;
                } else {