Issues (51)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

device/index-functions.php (12 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * This file contains functions called by index-site.php. The index-site.php
5
 * file should include this file with the following statement at the top:
6
 *
7
 * require_once __DIR__ . '/index-functions.php';
8
 */
9
10
use CILogon\Service\Util;
11
use CILogon\Service\Content;
12
use CILogon\Service\DBService;
13
use CILogon\Service\Loggit;
14
15
/**
16
 * printLogonPage
17
 *
18
 * This function first checks if the user_code has been entered and
19
 * matching client registration information has been found. If not, then go
20
 * to printUserCodePage instead. Otherwise, print out the HTML for the
21
 * "Select an Identity Provider" page along with the client registration
22
 * info.
23
 */
24
function printLogonPage()
0 ignored issues
show
The function printLogonPage() has been defined more than once; this definition is ignored, only the first definition in authorize/index-functions.php (L22-52) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
25
{
26
    if (!verifyUserCodeParam()) {
27
        printUserCodePage();
28
    } else {
29
        $log = new Loggit();
30
        $log->info('Welcome page hit.');
31
32
        Content::printHeader(
33
            'Welcome To The CILogon Device Authorization Service'
34
        );
35
36
        Content::printOIDCConsent();
0 ignored issues
show
The method printOIDCConsent() does not seem to exist on object<CILogon\Service\Content>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
37
        Content::printWAYF(true, true);
0 ignored issues
show
The call to Content::printWAYF() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
38
        Content::printFooter();
39
    }
40
}
41
42
/**
43
 * printUserCodePage
44
 *
45
 * If the user has not yet entered a user_code, or if the previously entered
46
 * user_code has expired or is not found, print out a form to prompt the
47
 * user to enter the device user_code.
48
 */
49
function printUserCodePage()
50
{
51
    $log = new Loggit();
52
    $log->info('User code page hit.');
53
54
    Content::printHeader(
55
        'Welcome To The CILogon Device Authorization Service'
56
    );
57
    Content::printCollapseBegin(
58
        'usercodedefault',
59
        'CILogon Device Flow User Code',
60
        false
61
    );
62
63
    // Check for any previously generated error message
64
    $user_code_error_msg = Util::getSessionVar('user_code_error_msg');
65
    Util::unsetSessionVar('user_code_error_msg');
66
    if (strlen($user_code_error_msg) > 0) {
67
        echo '
68
            <div class="alert alert-danger alert-dismissable fade show" role="alert">';
69
        echo $user_code_error_msg;
70
        echo '
71
              <button type="button" class="close" data-dismiss="alert"
72
                      aria-label="Close">
73
                <span aria-hidden="true">&times;</span>
74
              </button>
75
            </div>';
76
    }
77
78
    echo '
79
      <div class="card-body px-5">
80
        <div class="card-text my-2">
81
          Please enter the user code displayed on your device.
82
          If you do not have a user code, please proceed to the main
83
          <a href="..">CILogon site</a>.
84
        </div> <!-- end row -->
85
    ';
86
87
    Content::printFormHead();
88
89
    echo '
90
        <div class="form-group col-lg-6 offset-lg-3 col-md-8 offset-md-2 col-sm-10 offset-sm-1 mt-3">
91
          <label for="user-code">Enter User Code</label>
92
          <div class="form-row">
93
            <div class="col-11">
94
              <input type="text" name="user_code" id="user-code"
95
              required="required" autocomplete="off" maxlength="40"
96
              class="form-control upper" aria-describedby="user-code-help"
97
              oninput="this.value=this.value.replace(/[^a-zA-Z0-9\-\s\_]/,\'\'); upperCaseF(this);"
98
              title="User code is alphanumeric"/>
99
              <div class="invalid-tooltip">
100
                Please enter a valid user code.
101
              </div>
102
            </div>
103
          </div>
104
          <div class="form-row">
105
            <div class="col-11">
106
              <small id="user-code-help" class="form-text text-muted">
107
                Enter the user code displayed on your device.
108
              </small>
109
            </div>
110
          </div>
111
        </div> <!-- end form-group -->
112
113
        <div class="form-group">
114
          <div class="form-row align-items-center">
115
            <div class="col text-center">
116
              <input type="submit" name="submit"
117
              class="btn btn-primary submit"
118
              value="Enter User Code"/>
119
            </div>
120
          </div>
121
        </div> <!-- end form-group -->
122
123
        </form>
124
      </div> <!-- end card-body-->';
125
126
    Content::printCollapseEnd();
127
    Content::printFooter();
128
}
129
130
/**
131
 * printMainPage
132
 *
133
 * This is the page the user is redirected to after successfully logging in
134
 * with their chosen identity provider OR when the user clicks the 'Cancel'
135
 * button to deny the device authorization grant flow. When the 'Cancel'
136
 * button is clicked, a PHP session variable 'user_code_denied' is set. In
137
 * either case, if the PHP session contains the user_code entered by the
138
 * user, the userCodeApproved dbService method is called to let the OA4MP
139
 * service know that the user has approved/denied use of the user_code.
140
 */
141
function printMainPage()
0 ignored issues
show
The function printMainPage() has been defined more than once; this definition is ignored, only the first definition in authorize/index-functions.php (L126-224) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
142
{
143
    $log = new Loggit();
144
145
    // If user_code_denied is set (by clicking 'Cancel') then set approved
146
    // to zero when calling userCodeApproved.
147
    $user_code_approved = 1; // Assume user approved use of the user_code
148
    if (strlen(Util::getSessionVar('user_code_denied')) > 0) {
149
        Util::unsetSessionVar('user_code_denied');
150
        $user_code_approved = 0;
151
    }
152
153
    // Check the PHP session for the user_code entered by the user
154
    $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
155
    Util::unsetSessionVar('clientparams');
156
    $user_code = @$clientparams['user_code'];
157
158
    $errstr = '';
159
    if (strlen($user_code) > 0) {
160
        $log->info('Calling userCodeApproved dbService method...');
161
        $dbs = new DBService();
162
        if (
163
            ($dbs->userCodeApproved($user_code, $user_code_approved)) &&
0 ignored issues
show
The method userCodeApproved() does not seem to exist on object<CILogon\Service\DBService>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
164
            (!($dbs->status & 1))
165
        ) { // STATUS_OK codes are even
166
            // SUCCESSFULLY told database about decision to approve/deny
167
        } else { // STATUS_ERROR code returned
168
            // There was a problem with the user_code
169
            $errstr = 'Error confirming user code.'; // Generic error message
170
            if (!is_null($dbs->status)) {
171
                $errstr = array_search($dbs->status, DBService::$STATUS);
172
                // Customize error messages for Device Authz Grant flow
173
                if ($dbs->status == 0x10001) {
174
                    $errstr = 'Error confirming user code: Code not found. ' .
175
                        'This can happen when the user code has expired and ' .
176
                        'is no longer avaiable in the system.';
177
                } elseif ($db->status == 0x10003) {
0 ignored issues
show
The variable $db does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
178
                    $errstr = 'Error confirming user code: Code expired. ' .
179
                        'Please return to your device and start a new request.';
180
                }
181
            }
182
        }
183
    } else { // No user_code in PHP session - weird error!
184
        $errstr = 'Error confirming user code: Code not found. ' .
185
            'Please enable cookies in your web browser.';
186
    }
187
188
    $log->info('User Code Verified page hit.');
189
190
    Content::printHeader('User Code Approval');
191
    Content::printCollapseBegin(
192
        'usercodeapproval',
193
        'CILogon User Code Verification',
194
        false
195
    );
196
197
    // Check for any previously generated error message
198
    if (strlen($errstr) > 0) {
199
        echo '
200
            <div class="alert alert-danger show" role="alert">';
201
        echo $errstr;
202
        echo '
203
            </div>';
204
    } else {
205
        echo '
206
      <div class="card-body px-5">
207
        <div class="row my-3">
208
          <div class="col-1 text-center">
209
            <large>
210
        ',
211
        ($user_code_approved ?
212
            Content::getIcon('fa-check-square fa-2x', 'lime') :
213
            Content::getIcon('fa-times-circle fa-2x', 'red')
214
        ),
215
        '    
216
            </large>
217
          </div>
218
          <div class="col">
219
            You have successfully ' .
220
            ($user_code_approved ? 'approved ' : 'denied ') .
221
            'the user code. Please return to your device for further
222
            instructions.
223
          </div>
224
        </div>
225
226
      </div> <!-- end card-body-->';
227
    }
228
229
    Content::printCollapseEnd();
230
    Content::printFooter();
231
}
232
233
/**
234
 * verifyUserCodeParam
235
 *
236
 * This function checks for the presence of a 'user_code' query parameter.
237
 * If found, the dbService checkUserCode action is called to get the
238
 * associated client_id. Then the database is queried to find the details of
239
 * that client_id. The results are stored in the clientparams PHP session
240
 * variable. If no user_code was passed in, then the clientparams PHP
241
 * session variable is used. The final check verifies that all required
242
 * client info is available. If all of that is true, then this function
243
 * returns true.
244
 *
245
 * @return bool True if all required client registration info associated
246
 *         with the user_code is available. False otherwise.
247
 */
248
function verifyUserCodeParam()
249
{
250
    $retval = false; // Assume user code & other session info is not valid
251
252
    $log = new Loggit();
253
254
    // If idphint/selected_idp were previously set in the clientparams
255
    // PHP session variable, get them this time around.
256
    $clientparams = array();
0 ignored issues
show
$clientparams is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
257
    $clientparams = @array_intersect_key(
258
        json_decode(Util::getSessionVar('clientparams'), true),
259
        ['idphint' => 1, 'selected_idp' => 1]
260
    );
261
262
    // If a user_code was passed in, use that to get the associated
263
    // clientparams. Otherwise, get clientparams from the PHP session.
264
    $user_code = Util::getGetorPostVar('user_code');
265
    if (strlen($user_code) > 0) {
266
        Util::unsetSessionVar('clientparams'); // Don't use any previous values
267
        $log->info('Calling checkUserCode dbService method...');
268
        $dbs = new DBService();
269
        if (
270
            ($dbs->checkUserCode($user_code)) &&
0 ignored issues
show
The method checkUserCode() does not seem to exist on object<CILogon\Service\DBService>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
271
            (!($dbs->status & 1))
272
        ) { // STATUS_OK codes are even
273
            if (strlen($dbs->client_id) > 0) {
274
                // Use the client_id associated with the user_code to get
275
                // the rest of the OAuth2 client registration information.
276
                $clientparams['user_code'] = $dbs->user_code;
0 ignored issues
show
The property user_code does not seem to exist in CILogon\Service\DBService.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
277
                $clientparams['client_id'] = $dbs->client_id;
0 ignored issues
show
The property client_id does not seem to exist in CILogon\Service\DBService.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
278
                $clientparams['scope'] = $dbs->scope;
0 ignored issues
show
The property scope does not seem to exist in CILogon\Service\DBService.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
279
                // getOIDCClientParams assumes client_id is stored in the
280
                // passed-in $clientparams variable.
281
                Util::getOIDCClientParams($clientparams);
282
                // If no scope was requested, then assume ALL scopes
283
                // 'scope' is a space-separated string, while
284
                // client_scopes is a JSON list; need to transform into
285
                // space-separated string.
286
                if (strlen($clientparams['scope']) == 0) {
287
                    $clientparams['scope'] = implode(
288
                        ' ',
289
                        json_decode($clientparams['client_scopes'], true)
290
                    );
291
                }
292
            } else {
293
                Util::setSessionVar('user_code_error_msg', 'Unable to find a client matching the user code.');
294
            }
295
        } else { // STATUS_ERROR code returned
296
            $errstr = 'Error checking user code.'; // Generic error message
297
            if (!is_null($dbs->status)) {
298
                $errstr = array_search($dbs->status, DBService::$STATUS);
299
                // Customize error messages for Device Authz Grant flow
300
                if ($dbs->status == 0x10001) {
301
                    $errstr = 'User code not found.';
302
                } elseif ($db->status == 0x10003) {
0 ignored issues
show
The variable $db does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
303
                    $errstr = 'User code expired.';
304
                }
305
            }
306
            Util::setSessionVar('user_code_error_msg', $errstr);
307
        }
308
    } else { // No user_code passed in, so check the PHP session clientparams
309
        $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
310
    }
311
312
    // If no error so far, check all of the client parameters
313
    if (
314
        (strlen(Util::getSessionVar('user_code_error_msg')) == 0) &&
315
        (isset($clientparams['user_code'])) &&
316
        (isset($clientparams['client_id'])) &&
317
        (isset($clientparams['scope'])) &&
318
        (isset($clientparams['client_name'])) &&
319
        (isset($clientparams['client_home_url'])) &&
320
        (isset($clientparams['client_callback_uri'])) &&
321
        (isset($clientparams['client_scopes'])) &&
322
        (isset($clientparams['clientstatus'])) &&
323
        (!($clientparams['clientstatus'] & 1))
324
    ) { // STATUS_OK codes are even
325
        $retval = true;
326
        Util::setSessionVar('clientparams', json_encode($clientparams));
327
    } else {
328
        Util::unsetSessionVar('clientparams');
329
    }
330
331
    // Save idphint/selected_idp from query parameters to PHP session
332
    $idphint = Util::getGetVar('idphint');
333
    $selected_idp = Util::getGetVar('selected_idp');
334
    if (
335
        (strlen($idphint) > 0) ||
336
        (strlen($selected_idp) > 0)
337
    ) {
338
        if (strlen($idphint) > 0) {
339
            $clientparams['idphint'] = $idphint;
340
        }
341
        if (strlen($selected_idp) > 0) {
342
            $clientparams['selected_idp'] = $selected_idp;
343
        }
344
        Util::setSessionVar('clientparams', json_encode($clientparams));
345
    }
346
347
    return $retval;
348
}
349