GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — 2.6.x (#2509)
by Nicolas
04:59
created

XSRF::generateNonce()   C

Complexity

Conditions 9
Paths 13

Size

Total Lines 51
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 9
eloc 23
c 2
b 0
f 1
nc 13
nop 1
dl 0
loc 51
rs 6.2727

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
if (!defined("__IN_SYMPHONY__")) {
4
    die("You cannot directly access this file.");
5
}
6
7
/**
8
 * @package toolkit
9
 */
10
11
/**
12
 * The `XSRF` class provides protection for mitigating XRSF/CSRF attacks.
13
 *
14
 * @since Symphony 2.4
15
 * @author Rich Adams, http://richadams.me
16
 */
17
class XSRF
18
{
19
    /**
20
     * Return's the location of the XSRF tokens in the Session
21
     *
22
     * @return string|null
23
     */
24
    public static function getSessionToken()
0 ignored issues
show
Coding Style introduced by
getSessionToken uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
25
    {
26
        $token = $_SESSION[__SYM_COOKIE_PREFIX__]['xsrf-token'];
27
28
        if (is_array($token)) {
29
            $token = key($token);
30
        }
31
32
        return is_null($token) ? null : $token;
33
    }
34
35
    /**
36
     * Adds a token to the Session
37
     *
38
     * @param array $token
39
     */
40
    public static function setSessionToken($token = array())
0 ignored issues
show
Coding Style introduced by
setSessionToken uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
41
    {
42
        $_SESSION[__SYM_COOKIE_PREFIX__]['xsrf-token'] = $token;
43
    }
44
45
    /**
46
     * Removes the token from the Session
47
     *
48
     * @param string $token
49
     */
50
    public static function removeSessionToken($token = null)
0 ignored issues
show
Coding Style introduced by
removeSessionToken uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
51
    {
52
        if (is_null($token)) {
53
            return;
54
        }
55
56
        $_SESSION[__SYM_COOKIE_PREFIX__]['xsrf-token'] = null;
57
    }
58
59
    /**
60
     * Generates nonce to a desired `$length` using `openssl` where available,
61
     * falling back to using `/dev/urandom` and a microtime implementation
62
     * otherwise
63
     *
64
     * @param integer $length optional. By default, 30.
65
     * @return string
66
     *  base64 encoded, url safe
67
     */
68
    public static function generateNonce($length = 30)
69
    {
70
        $random = null;
71
        if ($length < 1) {
72
            throw new Exception('$length must be greater than 0');
73
        }
74
75
        // Use the new PHP 7 random_bytes call, if available
76
        if (function_exists('random_bytes')) {
77
            $random = random_bytes($length);
78
        }
79
80
        // Try mcrypt package, if available
81
        else if (function_exists('mcrypt_create_iv')) {
82
            $random = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
83
        }
84
85
        // Get some random binary data from open ssl, if available
86
        else if (function_exists('openssl_random_pseudo_bytes')) {
87
            $random = openssl_random_pseudo_bytes($length);
88
        }
89
90
        // Fallback to /dev/urandom
91
        else if (is_readable('/dev/urandom')) {
92
            if (($handle = @fopen('/dev/urandom', 'rb')) !== false) {
93
                $random = @fread($handle, $length);
94
                @fclose($handle);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
95
            }
96
        }
97
98
        // Fallback if no random bytes were found
99
        if (!$random) {
100
            $random = microtime();
101
102
            for ($i = 0; $i < 1000; $i += $length) {
103
                $random = sha1(microtime() . $random);
104
            }
105
        }
106
107
        // Convert to base64
108
        $random = base64_encode($random);
109
110
        // Replace unsafe chars
111
        $random = strtr($random, '+/', '-_');
112
        $random = str_replace('=', '', $random);
113
114
        // Truncate the string to specified lengh
115
        $random = substr($random, 0, $length);
116
117
        return $random;
118
    }
119
120
    /**
121
     * Creates the form input to use to house the token
122
     *
123
     * @return XMLElement
124
     */
125
    public static function formToken()
126
    {
127
        // <input type="hidden" name="xsrf" value=" . self::getToken() . " />
128
        $obj = new XMLElement("input");
129
        $obj->setAttribute("type", "hidden");
130
        $obj->setAttribute("name", "xsrf");
131
        $obj->setAttribute("value", self::getToken());
132
        return $obj;
133
    }
134
135
    /**
136
     * This is the nonce used to stop CSRF/XSRF attacks. It's stored in the user session.
137
     *
138
     * @return string
139
     */
140
    public static function getToken()
141
    {
142
        $token = self::getSessionToken();
143
        if (is_null($token)) {
144
            $nonce = self::generateNonce();
145
            self::setSessionToken($nonce);
0 ignored issues
show
Documentation introduced by
$nonce is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
146
147
        // Handle old tokens (< 2.6.0)
148
        } elseif (is_array($token)) {
149
            $nonce = key($token);
150
            self::setSessionToken($nonce);
151
152
        // New style tokens
153
        } else {
154
            $nonce = $token;
155
        }
156
157
        return $nonce;
158
    }
159
160
    /**
161
     * This will determine if a token is valid.
162
     *
163
     * @param string $xsrf
164
     *  The token to validate
165
     * @return boolean
166
     */
167
    public static function validateToken($xsrf)
168
    {
169
        $token = self::getSessionToken();
170
171
        return $token === $xsrf;
172
    }
173
174
    /**
175
     * This will validate a request has a good token.
176
     *
177
     * @throws SymphonyErrorPage
178
     * @param boolean $silent
179
     *  If true, this function will return false if the request fails,
180
     *  otherwise it will throw an Exception. By default this function
181
     *  will thrown an exception if the request is invalid.
182
     * @return false|void
183
     */
184
    public static function validateRequest($silent = false)
0 ignored issues
show
Coding Style introduced by
validateRequest uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
185
    {
186
        // Only care if we have a POST request.
187
        if (count($_POST) > 0) {
188
            if (!self::validateToken($_POST["xsrf"])) {
189
                // Token was invalid, show an error page.
190
                if (!$silent) {
191
                    self::throwXSRFException();
192
                } else {
193
                    return false;
194
                }
195
            }
196
        }
197
    }
198
199
    /**
200
     * The error function that's thrown if the token is invalid.
201
     *
202
     * @throws SymphonyErrorPage
203
     */
204
    public static function throwXSRFException()
205
    {
206
        $msg =
207
            __('Request was rejected for having an invalid cross-site request forgery token.')
208
            . '<br/><br/>' .
209
            __('Please go back and try again.');
210
        throw new SymphonyErrorPage($msg, __('Access Denied'), 'generic', array(), Page::HTTP_STATUS_FORBIDDEN);
211
    }
212
213
    /**
214
     * Return's the location of the XSRF tokens in the Session
215
     *
216
     * @deprecated This function will be removed in Symphony 3.0. Use
217
     *  `getSessionToken()` instead.
218
     * @return string|null
219
     */
220
    public static function getSession()
221
    {
222
        return self::getSessionToken();
223
    }
224
}
225