Passed
Push — master ( 3c2b3e...ec0aca )
by Terrence
12:54
created

Util::writeArrayToFile()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 5
nop 2
dl 0
loc 20
ccs 0
cts 7
cp 0
crap 30
rs 9.5222
c 0
b 0
f 0
1
<?php
2
3
namespace CILogon\Service;
4
5
use CILogon\Service\CSRF;
6
use CILogon\Service\Loggit;
7
use CILogon\Service\IdpList;
0 ignored issues
show
Bug introduced by
The type CILogon\Service\IdpList was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use CILogon\Service\DBService;
9
use CILogon\Service\SessionMgr;
10
use CILogon\Service\Skin;
11
use CILogon\Service\TimeIt;
12
use CILogon\Service\PortalCookie;
13
use PEAR;
14
use Config;
15
16
/**
17
 * Util
18
 *
19
 * This class contains a bunch of static (class) utility
20
 * methods, for example getting and setting server environment
21
 * variables and handling cookies. See the header for each function for
22
 * detailed description.
23
 */
24
class Util
25
{
26
    /**
27
     * @var array $ini_array Read the cilogon.ini file into an array
28
     */
29
    public static $ini_array = null;
30
31
    /**
32
     * @var TimeIt $timeit Initialize by calling static::startTiming() in
33
     * init().
34
     */
35
    public static $timeit;
36
37
    /**
38
     * @var IdPList $idplist A 'global' IdpList object since dplist.xml is
39
     *      large and expensive to create multiple times.
40
     */
41
    public static $idplist = null;
42
43
    /**
44
     * @var CSRF $csrf A 'global' CSRF token object to set the CSRF cookie
45
     * and print the hidden CSRF form element. Needs to be set only once
46
     * to keep the same CSRF value through the session.
47
     */
48
    public static $csrf = null;
49
50
    /**
51
     * @var Skin $skin A 'global' Skin object for skin configuration.
52
     */
53
    public static $skin = null;
54
55
    /**
56
     * @var array $oauth2idps An array of OAuth2 Identity Providers.
57
     */
58
    public static $oauth2idps = ['Google', 'GitHub', 'ORCID'];
59
60
61
    /**
62
     * getIdPList
63
     *
64
     * This function initializes the class $idplist object (if not yet
65
     * created) and returns it. This allows for a single 'global'
66
     * $idplist to be used by other classes (since creating an IdPList
67
     * object is expensive).
68
     *
69
     * @return IdPList The class instantiated IdPList object.
70
     **/
71
    public static function getIdpList()
72
    {
73
        if (is_null(static::$idplist)) {
74
            static::$idplist = new IdpList();
75
        }
76
        return static::$idplist;
77
    }
78
79
    /**
80
     * getCsrf
81
     *
82
     * This function initializes the class $csrf object (if not yet
83
     * created) and returns it. This allows for a single 'global'
84
     * $csrf to be used by other classes (since we want the CSRV value
85
     * to be consistent for the current page load).
86
     *
87
     * @return CSRF The class instantiated CSRF object.
88
     */
89
    public static function getCsrf()
90
    {
91
        if (is_null(static::$csrf)) {
92
            static::$csrf = new CSRF();
93
        }
94
        return static::$csrf;
95
    }
96
97
    /**
98
     * getSkin
99
     *
100
     * This function initializes the class $skin object (if not yet
101
     * created) and returns it. This allows for a single 'global'
102
     * $skin to be used by other classes (since loading the skin is
103
     * potentially expensive).
104
     *
105
     * @return The class instantiated Skin object.
0 ignored issues
show
Bug introduced by
The type CILogon\Service\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
106
     */
107
    public static function getSkin()
108
    {
109
        if (is_null(static::$skin)) {
110
            static::$skin = new Skin();
111
        }
112
        return static::$skin;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::skin returns the type CILogon\Service\Skin which is incompatible with the documented return type CILogon\Service\The.
Loading history...
113
    }
114
115
    /**
116
     * startTiming
117
     *
118
     * This function initializes the class variable $timeit which is
119
     * used for timing/benchmarking purposes.
120
     */
121
    public static function startTiming()
122
    {
123
        static::$timeit = new TimeIt(TimeIt::DEFAULTFILENAME, true);
124
    }
125
126
    /**
127
     * getServerVar
128
     *
129
     * This function queries a given $_SERVER variable (which is set
130
     * by the Apache server) and returns the value.
131
     *
132
     * @param string $serv The $_SERVER variable to query.
133
     * @return string The value of the $_SERVER variable or empty string
134
     *         if that variable is not set.
135
     */
136
    public static function getServerVar($serv)
137
    {
138
        $retval = '';
139
        if (isset($_SERVER[$serv])) {
140
            $retval = $_SERVER[$serv];
141
        }
142
        return $retval;
143
    }
144
145
    /**
146
     * getGetVar
147
     *
148
     * This function queries a given $_GET parameter (which is set in
149
     * the URL via a '?parameter=value' parameter) and returns the
150
     * value.
151
     *
152
     * @param string $get The $_GET variable to query.
153
     * @return string The value of the $_GET variable or empty string if
154
     *         that variable is not set.
155
     */
156
    public static function getGetVar($get)
157
    {
158
        $retval = '';
159
        if (isset($_GET[$get])) {
160
            $retval = $_GET[$get];
161
        }
162
        return $retval;
163
    }
164
165
    /**
166
     * getPostVar
167
     *
168
     * This function queries a given $_POST variable (which is set when
169
     * the user submits a form, for example) and returns the value.
170
     *
171
     * @param string $post The $_POST variable to query.
172
     * @return string The value of the $_POST variable or empty string if
173
     *         that variable is not set.
174
     */
175
    public static function getPostVar($post)
176
    {
177
        $retval = '';
178
        if (isset($_POST[$post])) {
179
            $retval = $_POST[$post];
180
        }
181
        return $retval;
182
    }
183
184
    /**
185
     * getGetOrPostVar
186
     *
187
     * This function looks for a $_GET or $_POST variable, with
188
     * preference given to $_GET if both are present.
189
     *
190
     * @param string $var The $_GET or $_POST variable to query.
191
     * @return string The value of the $_GET or $_POST variable
192
     *         if present. Empty string if variable is not set.
193
     */
194
    public static function getGetOrPostVar($var)
195
    {
196
        $retval = static::getGetVar($var);
197
        if (empty($retval)) {
198
            $retval = static::getPostVar($var);
199
        }
200
        return $retval;
201
    }
202
203
    /**
204
     * getCookieVar
205
     *
206
     * This function returns the value of a given cookie.
207
     *
208
     * @param string $cookie he $_COOKIE variable to query.
209
     * @return string The value of the $_COOKIE variable or empty string
210
     *         if that variable is not set.
211
     */
212
    public static function getCookieVar($cookie)
213
    {
214
        $retval = '';
215
        if (isset($_COOKIE[$cookie])) {
216
            $retval = $_COOKIE[$cookie];
217
        }
218
        return $retval;
219
    }
220
221
    /**
222
     * setCookieVar
223
     *
224
     * This function sets a cookie.
225
     *
226
     * @param string $cookie The name of the cookie to set.
227
     * @param string $value (Optional) The value to set for the cookie.
228
     *        Defaults to empty string.
229
     * @param int $exp The future expiration time (in seconds) of the
230
     *        cookie. Defaults to 1 year from now. If set to 0,
231
     *        the cookie expires at the end of the session.
232
     */
233
    public static function setCookieVar($cookie, $value = '', $exp = 31536000)
234
    {
235
        if ($exp > 0) {
236
            $exp += time();
237
        }
238
        setcookie($cookie, $value, $exp, '/', '.' . static::getDN(), true);
239
        $_COOKIE[$cookie] = $value;
240
    }
241
242
    /**
243
     * unsetCookieVar
244
     *
245
     * This function unsets a cookie. Strictly speaking, the cookie is
246
     * not removed, rather it is set to an empty value with an expired
247
     * time.
248
     *
249
     * @param string $cookie The name of the cookie to unset (delete).
250
     */
251
    public static function unsetCookieVar($cookie)
252
    {
253
        setcookie($cookie, '', 1, '/', '.' . static::getDN(), true);
254
        unset($_COOKIE[$cookie]);
255
    }
256
257
    /**
258
     * getPortalOrNormalCookieVar
259
     *
260
     * This is a convenience function which first checks if there is a
261
     * OAuth 1.0a ('delegate') or OIDC ('authorize') session active.
262
     * If so, it attempts to get the requested cookie from the
263
     * associated portalcookie. If there is not an OAuth/OIDC session
264
     * active, it looks for a 'normal' cookie. If you need a
265
     * portalcookie object to do multiple get/set method calls from
266
     * one function, it is probably better NOT to use this method since
267
     * creating the portalcookie object is potentially expensive.
268
     *
269
     * @param string $cookie The name of the cookie to get.
270
     * @return string The cookie value from either the portalcookie
271
     *         (in the case of an active OAuth session) or the
272
     *         'normal' cookie. Return empty string if no matching
273
     *         cookie in either place.
274
     */
275
    public static function getPortalOrNormalCookieVar($cookie)
276
    {
277
        $retval = '';
278
        $pc = new PortalCookie();
279
        $pn = $pc->getPortalName();
280
        if (strlen($pn) > 0) {
281
            $retval = $pc->get($cookie);
282
        } else {
283
            $retval = static::getCookieVar($cookie);
284
        }
285
        return $retval;
286
    }
287
288
    /**
289
     * getSessionVar
290
     *
291
     * This function returns the value of a given PHP Session variable.
292
     *
293
     * @param string $sess The $_SESSION variable to query.
294
     * @return string The value of the $_SESSION variable or empty string
295
     *         if that variable is not set.
296
     */
297
    public static function getSessionVar($sess)
298
    {
299
        $retval = '';
300
        if (isset($_SESSION[$sess])) {
301
            $retval = $_SESSION[$sess];
302
        }
303
        return $retval;
304
    }
305
306
    /**
307
     * setSessionVar
308
     *
309
     * This function can set or unset a given PHP session variable.
310
     * The first parameter is the PHP session variable to set/unset.
311
     * If the second parameter is the empty string, then the session
312
     * variable is unset.  Otherwise, the session variable is set to
313
     * the second parameter.  The function returns true if the session
314
     * variable was set to a non-empty value, false otherwise.
315
     * Normally, the return value can be ignored.
316
     *
317
     * @param string $key The name of the PHP session variable to set
318
     *        (or unset).
319
     * @param string $value (Optional) The value of the PHP session variable
320
     *        (to set), or empty string (to unset). Defaults to empty
321
     *        string (implies unset the session variable).
322
     * @return bool True if the PHP session variable was set to a
323
     *         non-empty string, false if variable was unset or if
324
     *         the specified session variable was not previously set.
325
     */
326
    public static function setSessionVar($key, $value = '')
327
    {
328
        $retval = false;  // Assume we want to unset the session variable
329
        if (strlen($key) > 0) {  // Make sure session var name was passed in
330
            if (strlen($value) > 0) {
331
                $_SESSION[$key] = $value;
332
                $retval = true;
333
            } else {
334
                static::unsetSessionVar($key);
335
            }
336
        }
337
        return $retval;
338
    }
339
340
    /**
341
     * unsetSessionVar
342
     *
343
     * This function clears the given PHP session variable by first
344
     * setting it to null and then unsetting it entirely.
345
     *
346
     * @param string $sess The $_SESSION variable to erase.
347
     */
348
    public static function unsetSessionVar($sess)
349
    {
350
        if (isset($_SESSION[$sess])) {
351
            $_SESSION[$sess] = null;
352
            unset($_SESSION[$sess]);
353
        }
354
    }
355
356
    /**
357
     * removeShibCookies
358
     *
359
     * This function removes all '_shib*' cookies currently in the
360
     * user's browser session. In effect, this logs the user out of
361
     * any IdP. Note that you must call this before you output any
362
     * HTML. Strictly speaking, the cookies are not removed, rather
363
     * they are set to empty values with expired times.
364
     */
365
    public static function removeShibCookies()
366
    {
367
        foreach ($_COOKIE as $key => $value) {
368
            if (strncmp($key, '_shib', strlen('_shib')) == 0) {
369
                static::unsetCookieVar($key);
370
            }
371
        }
372
    }
373
374
    /**
375
     * startPHPSession
376
     *
377
     * This function starts a secure PHP session and should be called
378
     * at the beginning of each script before any HTML is output.  It
379
     * does a trick of setting a 'lastaccess' time so that the
380
     * $_SESSION variable does not expire without warning.
381
     *
382
     * @param string $storetype (Optional) Storage location of the PHP
383
     *        session data, one of 'file' or 'mysql'. Defaults to null,
384
     *        which means use the value of STORAGE_PHPSESSIONS from the
385
     *        config.php file, or 'file' if no such parameter configured.
386
     */
387
    public static function startPHPSession($storetype = null)
0 ignored issues
show
Unused Code introduced by
The parameter $storetype is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

387
    public static function startPHPSession(/** @scrutinizer ignore-unused */ $storetype = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
388
    {
389
        // No parameter given? Use the value read in from cilogon.ini file.
390
        // If STORAGE_PHPSESSIONS == 'mysqli', create a sessionmgr().
391
        $storetype = STORAGE_PHPSESSIONS;
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\STORAGE_PHPSESSIONS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
392
393
        if (preg_match('/^mysql/', $storetype)) {
394
            $sessionmgr = new SessionMgr();
0 ignored issues
show
Unused Code introduced by
The assignment to $sessionmgr is dead and can be removed.
Loading history...
395
        }
396
397
        ini_set('session.cookie_secure', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

397
        ini_set('session.cookie_secure', /** @scrutinizer ignore-type */ true);
Loading history...
398
        ini_set('session.cookie_domain', '.' . static::getDN());
399
        session_start();
400
        if (
401
            (!isset($_SESSION['lastaccess']) ||
402
            (time() - $_SESSION['lastaccess']) > 60)
403
        ) {
404
            $_SESSION['lastaccess'] = time();
405
        }
406
    }
407
408
    /**
409
     * getScriptDir
410
     *
411
     * This function returns the directory (or full url) of the script
412
     * that is currently running.  The returned directory/url is
413
     * terminated by a '/' character (unless the second parameter is
414
     * set to true). This function is useful for those scripts named
415
     * index.php where we don't want to actually see 'index.php' in the
416
     * address bar (again, unless the second parameter is set to true).
417
     *
418
     * @param bool $prependhttp (Optional) Boolean to prepend 'http(s)://' to
419
     *        the script name. Defaults to false.
420
     * @param bool $stripfile (Optional) Boolean to strip off the trailing
421
     *        filename (e.g. index.php) from the path.
422
     *        Defaults to true (i.e., defaults to directory
423
     *        only without the trailing filename).
424
     * @return string The directory or url of the current script, with or
425
     *         without the trailing .php filename.
426
     */
427
    public static function getScriptDir($prependhttp = false, $stripfile = true)
428
    {
429
        $retval = static::getServerVar('SCRIPT_NAME');
430
        if ($stripfile) {
431
            $retval = dirname($retval);
432
        }
433
        if ($retval == '.') {
434
            $retval = '';
435
        }
436
        if (
437
            (strlen($retval) == 0) ||
438
            ($stripfile && ($retval[strlen($retval) - 1] != '/'))
439
        ) {
440
            $retval .= '/';  // Append a slash if necessary
441
        }
442
        if ($prependhttp) {  // Prepend http(s)://hostname
443
            $retval = 'http' .
444
                      ((strtolower(static::getServerVar('HTTPS')) == 'on') ? 's' : '') .
445
                      '://' . static::getServerVar('HTTP_HOST') . $retval;
446
        }
447
        return $retval;
448
    }
449
450
    /**
451
     * tempDir
452
     *
453
     * This function creates a temporary subdirectory within the
454
     * specified subdirectory. The new directory name is composed of
455
     * 16 hexadecimal letters, plus any prefix if you specify one. The
456
     * full path of the the newly created directory is returned.
457
     *
458
     * @param string $dir The full path to the containing directory.
459
     * @param string $prefix (Optional) A prefix for the new temporary
460
     *        directory. Defaults to empty string.
461
     * @param int $mode (Optional) Access permissions for the new
462
     *        temporary directory. Defaults to 0775.
463
     * @return string Full path to the newly created temporary directory.
464
     */
465
    public static function tempDir($dir, $prefix = '', $mode = 0775)
466
    {
467
        if (substr($dir, -1) != '/') {
468
            $dir .= '/';
469
        }
470
471
        $path = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $path is dead and can be removed.
Loading history...
472
        do {
473
            $path = $dir . $prefix . sprintf("%08X%08X", mt_rand(), mt_rand());
474
        } while (!mkdir($path, $mode, true));
475
476
        return $path;
477
    }
478
479
    /**
480
     * deleteDir
481
     *
482
     * This function deletes a directory and all of its contents.
483
     *
484
     * @param string $dir The (possibly non-empty) directory to delete.
485
     * @param bool $shred (Optional) Shred the file before deleting?
486
     *        Defaults to false.
487
     */
488
    public static function deleteDir($dir, $shred = false)
489
    {
490
        if (is_dir($dir)) {
491
            $objects = scandir($dir);
492
            foreach ($objects as $object) {
493
                if ($object != "." && $object != "..") {
494
                    if (filetype($dir . "/" . $object) == "dir") {
495
                        static::deleteDir($dir . "/" . $object);
496
                    } else {
497
                        if ($shred) {
498
                            @exec('/bin/env /usr/bin/shred -u -z ' . $dir . "/" . $object);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for exec(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

498
                            /** @scrutinizer ignore-unhandled */ @exec('/bin/env /usr/bin/shred -u -z ' . $dir . "/" . $object);

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...
499
                        } else {
500
                            @unlink($dir . "/" . $object);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

500
                            /** @scrutinizer ignore-unhandled */ @unlink($dir . "/" . $object);

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...
501
                        }
502
                    }
503
                }
504
            }
505
            reset($objects);
0 ignored issues
show
Bug introduced by
It seems like $objects can also be of type false; however, parameter $array of reset() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

505
            reset(/** @scrutinizer ignore-type */ $objects);
Loading history...
506
            @rmdir($dir);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rmdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

506
            /** @scrutinizer ignore-unhandled */ @rmdir($dir);

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...
507
        }
508
    }
509
510
    /**
511
     * htmlent
512
     *
513
     * This method is necessary since htmlentities() does not seem to
514
     * obey the default arguments as documented in the PHP manual, and
515
     * instead encodes accented characters incorrectly. By specifying
516
     * the flags and encoding, the problem is solved.
517
     *
518
     * @param string $str : A string to process with htmlentities().
519
     * @return string The input string processed by htmlentities with
520
     *         specific options.
521
     */
522
    public static function htmlent($str)
523
    {
524
        return htmlentities($str, ENT_COMPAT | ENT_HTML401, 'UTF-8');
525
    }
526
527
    /**
528
     * sendErrorAlert
529
     *
530
     * Use this function to send an error message. The $summary should
531
     * be a short description of the error since it is placed in the
532
     * subject of the email. Put a more verbose description of the
533
     * error in the $detail parameter. Any session variables available
534
     * are appended to the body of the message.
535
     *
536
     * @param string $summary A brief summary of the error (in email subject)
537
     * @param string $detail A detailed description of the error (in the
538
     *        email body)
539
     * @param string $mailto (Optional) The destination email address.
540
     *        Defaults to '[email protected]'.
541
     */
542
    public static function sendErrorAlert(
543
        $summary,
544
        $detail,
545
        $mailto = '[email protected]'
546
    ) {
547
        $sessionvars = array(
548
            'idp'          => 'IdP ID',
549
            'idpname'      => 'IdP Name',
550
            'uid'          => 'Database UID',
551
            'dn'           => 'Cert DN',
552
            'firstname'    => 'First Name',
553
            'lastname'     => 'Last Name',
554
            'displayname'  => 'Display Name',
555
            'ePPN'         => 'ePPN',
556
            'ePTID'        => 'ePTID',
557
            'openID'       => 'OpenID ID',
558
            'oidcID'       => 'OIDC ID',
559
            'loa'          => 'LOA',
560
            'affiliation'  => 'Affiliation',
561
            'ou'           => 'OU',
562
            'memberof'     => 'MemberOf',
563
            'acr'          => 'AuthnContextClassRef',
564
            'entitlement'  => 'Entitlement',
565
            'itrustuin'    => 'iTrustUIN',
566
            'cilogon_skin' => 'Skin Name',
567
            'authntime'    => 'Authn Time'
568
        );
569
570
        $remoteaddr = static::getServerVar('REMOTE_ADDR');
571
        $remotehost = gethostbyaddr($remoteaddr);
572
        $mailfrom = 'From: [email protected]' . "\r\n" .
573
                    'X-Mailer: PHP/' . phpversion();
574
        $mailsubj = 'CILogon Service on ' . php_uname('n') .
575
                    ' - ' . $summary;
576
        $mailmsg  = '
577
CILogon Service - ' . $summary . '
578
-----------------------------------------------------------
579
' . $detail . '
580
581
Session Variables
582
-----------------
583
Timestamp     = ' . date(DATE_ATOM) . '
584
Server Host   = ' . static::getHN() . '
585
Remote Address= ' . $remoteaddr . '
586
' . (($remotehost !== false) ? "Remote Host   = $remotehost" : '') . '
587
';
588
589
        foreach ($sessionvars as $svar => $sname) {
590
            if (strlen($val = static::getSessionVar($svar)) > 0) {
591
                $mailmsg .= sprintf("%-14s= %s\n", $sname, $val);
592
            }
593
        }
594
595
        mail($mailto, $mailsubj, $mailmsg, $mailfrom);
596
    }
597
598
    /**
599
     * getFirstAndLastName
600
     *
601
     * This function attempts to get the first and last name of a user
602
     * extracted from the 'full name' (displayName) of the user.
603
     * Simply pass in all name info (full, first, and last) and the
604
     * function first tries to break up the full name into first/last.
605
     * If this is not sufficient, the function checks first and last
606
     * name. Finally, if either first or last is blank, the function
607
     * duplicates first <=> last so both names have the same value.
608
     * Note that even with all this, you still need to check if the
609
     * returned (first,last) names are blank.
610
     *
611
     * @param string $full The 'full name' of the user
612
     * @param string $first (Optional) The 'first name' of the user
613
     * @param string $last (Optional) The 'last name' of the user
614
     * @return array An array 'list(firstname,lastname)'
615
     */
616
    public static function getFirstAndLastName($full, $first = '', $last = '')
617
    {
618
        $firstname = '';
619
        $lastname = '';
620
621
        # Try to split the incoming $full name into first and last names
622
        if (strlen($full) > 0) {
623
            $names = preg_split('/\s+/', $full, 2);
624
            $firstname = @$names[0];
625
            $lastname =  @$names[1];
626
        }
627
628
        # If either first or last name blank, then use incoming $first and $last
629
        if (strlen($firstname) == 0) {
630
            $firstname = $first;
631
        }
632
        if (strlen($lastname) == 0) {
633
            $lastname = $last;
634
        }
635
636
        # Finally, if only a single name, copy first name <=> last name
637
        if (strlen($lastname) == 0) {
638
            $lastname = $firstname;
639
        }
640
        if (strlen($firstname) == 0) {
641
            $firstname = $lastname;
642
        }
643
644
        # Return both names as an array (i.e., use list($first,last)=...)
645
        return array($firstname,$lastname);
646
    }
647
648
    /**
649
     * getHN
650
     *
651
     * This function calculates and returns the 'hostname' for the
652
     * server. It first checks HTTP_HOST. If not set, it returns
653
     * 'cilogon.org'. This is needed by command line scripts.
654
     *
655
     * @return string The 'Hostname' for the web server.
656
     */
657
    public static function getHN()
658
    {
659
        $thehostname = static::getServerVar('HTTP_HOST');
660
        if (strlen($thehostname) == 0) {
661
            $thehostname = 'cilogon.org';
662
        }
663
        return $thehostname;
664
    }
665
666
    /**
667
     * getDN
668
     *
669
     * This function calculates and returns the 'domainname' for the
670
     * server. It uses the hostname value calculated by getHN() and
671
     * uses the last two segments.
672
     *
673
     * @return string The 'Domainname' for the web server.
674
     */
675
    public static function getDN()
676
    {
677
        $thedomainname = static::getHN();
678
        if (preg_match('/[^\.]+\.[^\.]+$/', $thedomainname, $matches)) {
679
            $thedomainname = $matches[0];
680
        }
681
        return $thedomainname;
682
    }
683
684
    /**
685
     * getAuthzUrl
686
     *
687
     * This funtion takes in the name of an IdP (e.g., 'Google') and
688
     * returns the assoicated OAuth2 authorization URL.
689
     *
690
     * @param string $idp The name of an OAuth2 Identity Provider.
691
     * @return string The authorization URL for the given IdP.
692
     */
693
    public static function getAuthzUrl($idp)
694
    {
695
        $url = null;
696
        $idptourl = array(
697
            'Google' => 'https://accounts.google.com/o/oauth2/auth',
698
            'GitHub' => 'https://github.com/login/oauth/authorize',
699
            'ORCID'  => 'https://orcid.org/oauth/authorize',
700
        );
701
        if (array_key_exists($idp, $idptourl)) {
702
            $url = $idptourl[$idp];
703
        }
704
        return $url;
705
    }
706
707
    /**
708
     * getAuthzIdP
709
     *
710
     * This function takes in the OAuth2 authorization URL and returns
711
     * the associated pretty-print name of the IdP.
712
     *
713
     * @param string $url The authorization URL of an OAuth2 Identity Provider.
714
     * @return string The name of the IdP.
715
     */
716
    public static function getAuthzIdP($url)
717
    {
718
        $idp = null;
719
        $urltoidp = array(
720
            'https://accounts.google.com/o/oauth2/auth' => 'Google',
721
            'https://github.com/login/oauth/authorize'  => 'GitHub',
722
            'https://orcid.org/oauth/authorize'         => 'ORCID',
723
        );
724
        if (array_key_exists($url, $urltoidp)) {
725
            $idp = $urltoidp[$url];
726
        }
727
        return $idp;
728
    }
729
730
    /**
731
     * saveUserToDataStore
732
     *
733
     * This function is called when a user logs on to save identity
734
     * information to the datastore. As it is used by both Shibboleth
735
     * and OpenID Identity Providers, some parameters passed in may
736
     * be blank (empty string). If the function verifies that the minimal
737
     * sets of parameters are valid, the dbservice servlet is called
738
     * to save the user info. Then various session variables are set
739
     * for use by the program later on. In case of error, an email
740
     * alert is sent showing the missing parameters.
741
     *
742
     * @param mixed $args Variable number of paramters ordered as follows:
743
     *     remoteuser -The REMOTE_USER from HTTP headers
744
     *     idp - The provider IdP Identifier / URL endpoint
745
     *     idpname - The pretty print provider IdP name
746
     *     firstname - The user's first name
747
     *     lastname - The user's last name
748
     *     displayname - The user's display name
749
     *     emailaddr-  The user's email address
750
     *     loa - The level of assurance (e.g., openid/basic/silver)
751
     *     ePPN - User's ePPN (for SAML IdPs)
752
     *     ePTID - User's ePTID (for SAML IdPs)
753
     *     openidID - User's OpenID 2.0 Identifier (Google deprecated)
754
     *     oidcID - User's OpenID Connect Identifier
755
     *     affiliation - User's affiliation
756
     *     ou - User's organizational unit (OU)
757
     *     memberof - User's isMemberOf group info
758
     *     acr - Authentication Context Class Ref
759
     *     entitlement - User's entitlement
760
     *     itrustuin - User's univerity ID number
761
     */
762
    public static function saveUserToDataStore(...$args)
763
    {
764
        $dbs = new DBService();
765
766
        // Save the passed-in variables to the session for later use
767
        // (e.g., by the error handler in handleGotUser). Then get these
768
        // session variables into local vars for ease of use.
769
        static::setUserAttributeSessionVars(...$args);
770
        $remoteuser  = static::getSessionVar('remoteuser');
771
        $idp         = static::getSessionVar('idp');
772
        $idpname     = static::getSessionVar('idpname');
773
        $firstname   = static::getSessionVar('firstname');
774
        $lastname    = static::getSessionVar('lastname');
775
        $displayname = static::getSessionVar('displayname');
776
        $emailaddr   = static::getSessionvar('emailaddr');
777
        $loa         = static::getSessionVar('loa');
778
        $ePPN        = static::getSessionVar('ePPN');
779
        $ePTID       = static::getSessionVar('ePTID');
780
        $openidID    = static::getSessionVar('openidID');
781
        $oidcID      = static::getSessionVar('oidcID');
782
        $affiliation = static::getSessionVar('affiliation');
783
        $ou          = static::getSessionVar('ou');
784
        $memberof    = static::getSessionVar('memberof');
785
        $acr         = static::getSessionVar('acr');
786
        $entitlement = static::getSessionVar('entitlement');
787
        $itrustuin   = static::getSessionVar('itrustuin');
788
789
        static::setSessionVar('submit', static::getSessionVar('responsesubmit'));
790
791
        // Make sure parameters are not empty strings, and email is valid
792
        // Must have at least one of remoteuser/ePPN/ePTID/openidID/oidcID
793
        if (
794
            ((strlen($remoteuser) > 0) ||
795
               (strlen($ePPN) > 0) ||
796
               (strlen($ePTID) > 0) ||
797
               (strlen($openidID) > 0) ||
798
               (strlen($oidcID) > 0)) &&
799
            (strlen($idp) > 0) &&
800
            (strlen($idpname) > 0)  &&
801
            (strlen($firstname) > 0) &&
802
            (strlen($lastname) > 0) &&
803
            (strlen($emailaddr) > 0) &&
804
            (filter_var($emailaddr, FILTER_VALIDATE_EMAIL))
805
        ) {
806
            // For the new Google OAuth 2.0 endpoint, we want to keep the
807
            // old Google OpenID endpoint URL in the database (so user does
808
            // not get a new certificate subject DN). Change the idp
809
            // and idpname to the old Google OpenID values.
810
            if (
811
                ($idpname == 'Google+') ||
812
                ($idp == static::getAuthzUrl('Google'))
813
            ) {
814
                $idpname = 'Google';
815
                $idp = 'https://www.google.com/accounts/o8/id';
816
            }
817
818
            // In the database, keep a consistent ProviderId format: only
819
            // allow 'http' (not 'https') and remove any 'www.' prefix.
820
            if ($loa == 'openid') {
821
                $idp = preg_replace('%^https://(www\.)?%', 'http://', $idp);
822
            }
823
824
            $result = $dbs->getUser(
825
                $remoteuser,
826
                $idp,
827
                $idpname,
828
                $firstname,
829
                $lastname,
830
                $displayname,
831
                $emailaddr,
832
                $ePPN,
833
                $ePTID,
834
                $openidID,
835
                $oidcID,
836
                $affiliation,
837
                $ou,
838
                $memberof,
839
                $acr,
840
                $entitlement,
841
                $itrustuin
842
            );
843
            static::setSessionVar('uid', $dbs->user_uid);
844
            static::setSessionVar('dn', $dbs->distinguished_name);
845
            static::setSessionVar('status', $dbs->status);
846
            if (!$result) {
847
                static::sendErrorAlert(
848
                    'dbService Error',
849
                    'Error calling dbservice action "getUser" in ' .
850
                    'saveUserToDatastore() method.'
851
                );
852
            }
853
        } else { // Missing one or more required attributes
854
            static::setSessionVar(
855
                'status',
856
                DBService::$STATUS['STATUS_MISSING_PARAMETER_ERROR']
857
            );
858
        }
859
860
        // If 'status' is not STATUS_OK*, then send an error email
861
        $status = static::getSessionVar('status');
862
        if ($status & 1) { // Bad status codes are odd
863
            // For missing parameter errors, log an error message
864
            if (
865
                $status ==
866
                DBService::$STATUS['STATUS_MISSING_PARAMETER_ERROR']
867
            ) {
868
                $log = new Loggit();
869
                $log->error('STATUS_MISSING_PARAMETER_ERROR', true);
870
            }
871
872
            // For other dbservice errors OR for any error involving
873
            // LIGO (e.g., missing parameter error), send email alert.
874
            if (
875
                ($status !=
876
                    DBService::$STATUS['STATUS_MISSING_PARAMETER_ERROR']) ||
877
                (preg_match('/ligo\.org/', $idp))
878
            ) {
879
                $mailto = '[email protected]';
880
881
                // Set $disableligoalerts = true to stop LIGO failures
882
                // from being sent to '[email protected]', but still
883
                // sent to '[email protected]'.
884
                $disableligoalerts = false;
885
886
                // Fixes CIL-205 - Notify LIGO about IdP login errors
887
                if (preg_match('/ligo\.org/', $idp)) {
888
                    if ($disableligoalerts) {
0 ignored issues
show
introduced by
The condition $disableligoalerts is always false.
Loading history...
889
                        $mailto = '';
890
                    }
891
                    $mailto .= ((strlen($mailto) > 0) ? ',' : '') .
892
                        '[email protected]';
893
                }
894
895
                static::sendErrorAlert(
896
                    'Failure in ' .
897
                        (($loa == 'openid') ? '' : '/secure') . '/getuser/',
898
                    'Remote_User   = ' . ((strlen($remoteuser) > 0) ?
899
                        $remoteuser : '<MISSING>') . "\n" .
900
                    'IdP ID        = ' . ((strlen($idp) > 0) ?
901
                        $idp : '<MISSING>') . "\n" .
902
                    'IdP Name      = ' . ((strlen($idpname) > 0) ?
903
                        $idpname : '<MISSING>') . "\n" .
904
                    'First Name    = ' . ((strlen($firstname) > 0) ?
905
                        $firstname : '<MISSING>') . "\n" .
906
                    'Last Name     = ' . ((strlen($lastname) > 0) ?
907
                        $lastname : '<MISSING>') . "\n" .
908
                    'Display Name  = ' . ((strlen($displayname) > 0) ?
909
                        $displayname : '<MISSING>') . "\n" .
910
                    'Email Address = ' . ((strlen($emailaddr) > 0) ?
911
                        $emailaddr : '<MISSING>') . "\n" .
912
                    'ePPN          = ' . ((strlen($ePPN) > 0) ?
913
                        $ePPN : '<MISSING>') . "\n" .
914
                    'ePTID         = ' . ((strlen($ePTID) > 0) ?
915
                        $ePTID : '<MISSING>') . "\n" .
916
                    'OpenID ID     = ' . ((strlen($openidID) > 0) ?
917
                        $openidID : '<MISSING>') . "\n" .
918
                    'OIDC ID       = ' . ((strlen($oidcID) > 0) ?
919
                        $oidcID : '<MISSING>') . "\n" .
920
                    'Affiliation   = ' . ((strlen($affiliation) > 0) ?
921
                        $affiliation : '<MISSING>') . "\n" .
922
                    'OU            = ' . ((strlen($ou) > 0) ?
923
                        $ou : '<MISSING>') . "\n" .
924
                    'MemberOf      = ' . ((strlen($memberof) > 0) ?
925
                        $memberof : '<MISSING>') . "\n" .
926
                    'ACR           = ' . ((strlen($acr) > 0) ?
927
                        $acr : '<MISSING>') . "\n" .
928
                    'Entitlement   = ' . ((strlen($entitlement) > 0) ?
929
                        $entitlement : '<MISSING>') . "\n" .
930
                    'iTrustUIN     = ' . ((strlen($itrustuin) > 0) ?
931
                        $itrustuin : '<MISSING>') . "\n" .
932
                    'Database UID  = ' . ((strlen(
933
                        $i = static::getSessionVar('uid')
934
                    ) > 0) ?  $i : '<MISSING>') . "\n" .
935
                    'Status Code   = ' . ((strlen(
0 ignored issues
show
Bug introduced by
Are you sure strlen($i = array_search... > 0 ? $i : '<MISSING>' of type false|integer|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

935
                    'Status Code   = ' . (/** @scrutinizer ignore-type */ (strlen(
Loading history...
936
                        $i = array_search(
0 ignored issues
show
Bug introduced by
It seems like $i = array_search($statu...vice\DBService::STATUS) can also be of type false; however, parameter $string of strlen() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

936
                        /** @scrutinizer ignore-type */ $i = array_search(
Loading history...
937
                            $status,
938
                            DBService::$STATUS
939
                        )
940
                    ) > 0) ?  $i : '<MISSING>'),
941
                    $mailto
942
                );
943
            }
944
            static::unsetSessionVar('authntime');
945
        } else { // status is okay, set authntime
946
            static::setSessionVar('authntime', time());
947
        }
948
949
        static::unsetSessionVar('responsesubmit');
950
        static::unsetSessionVar('requestsilver');
951
952
        static::getCsrf()->setCookieAndSession();
953
    }
954
955
    /**
956
     * setUserAttributeSessionVars
957
     *
958
     * This method is called by saveUserToDatastore to put the passsed-in
959
     * variables into the PHP session for later use.
960
     *
961
     * @param mixed $args Variable number of user attribute paramters
962
     *        ordered as shown in the $attrs array below.
963
     */
964
    public static function setUserAttributeSessionVars(...$args)
965
    {
966
        $attrs = array('remoteuser', 'idp', 'idpname', 'firstname',
967
                       'lastname', 'displayname', 'emailaddr',
968
                       'loa', 'ePPN', 'ePTID', 'openidID', 'oidcID',
969
                       'affiliation', 'ou', 'memberof', 'acr',
970
                       'entitlement', 'itrustuin');
971
        $numargs = count($args);
972
        for ($i = 0; $i < $numargs; $i++) {
973
            static::setSessionVar($attrs[$i], $args[$i]);
974
        }
975
976
        // CACC-238 - Set loa to "silver" if the following are true:
977
        // (1) loa contains  https://refeds.org/assurance/profile/cappuccino
978
        // (2) acr is either https://refeds.org/profile/sfa or
979
        //                   https://refeds.org/profile/mfa
980
        if (
981
            (preg_match('%https://refeds.org/assurance/profile/cappuccino%', static::getSessionVar('loa'))) &&
982
            (preg_match('%https://refeds.org/profile/[ms]fa%', static::getSessionVar('acr')))
983
        ) {
984
            static::setSessionVar('loa', 'http://incommonfederation.org/assurance/silver');
985
        }
986
    }
987
988
    /**
989
     * unsetClientSessionVars
990
     *
991
     * This function removes all of the PHP session variables related to
992
     * the client session.
993
     */
994
    public static function unsetClientSessionVars()
995
    {
996
        static::unsetSessionVar('submit');
997
998
        // Specific to 'Download Certificate' page
999
        static::unsetSessionVar('p12');
1000
        static::unsetSessionVar('p12lifetime');
1001
        static::unsetSessionVar('p12multiplier');
1002
1003
        // Specific to OAuth 1.0a flow
1004
        static::unsetSessionVar('portalstatus');
1005
        static::unsetSessionVar('callbackuri');
1006
        static::unsetSessionVar('successuri');
1007
        static::unsetSessionVar('failureuri');
1008
        static::unsetSessionVar('portalname');
1009
        static::unsetSessionVar('tempcred');
1010
1011
        // Specific to OIDC flow
1012
        static::unsetSessionVar('clientparams');
1013
    }
1014
1015
    /**
1016
     * unsetUserSessionVars
1017
     *
1018
     * This function removes all of the PHP session variables related to
1019
     * the user's session.  This will force the user to log on (again)
1020
     * with their IdP and call the 'getuser' script to repopulate the PHP
1021
     * session.
1022
     */
1023
    public static function unsetUserSessionVars()
1024
    {
1025
        // Needed for verifyCurrentUserSession
1026
        static::unsetSessionVar('idp');
1027
        static::unsetSessionVar('idpname');
1028
        static::unsetSessionVar('status');
1029
        static::unsetSessionVar('uid');
1030
        static::unsetSessionVar('dn');
1031
        static::unsetSessionVar('authntime');
1032
1033
        // Variables set by getuser
1034
        static::unsetSessionVar('firstname');
1035
        static::unsetSessionVar('lastname');
1036
        static::unsetSessionVar('displayname');
1037
        static::unsetSessionVar('emailaddr');
1038
        static::unsetSessionVar('loa');
1039
        static::unsetSessionVar('ePPN');
1040
        static::unsetSessionVar('ePTID');
1041
        static::unsetSessionVar('openidID');
1042
        static::unsetSessionVar('oidcID');
1043
        static::unsetSessionVar('affiliation');
1044
        static::unsetSessionVar('ou');
1045
        static::unsetSessionVar('memberof');
1046
        static::unsetSessionVar('acr');
1047
        static::unsetSessionVar('entitlement');
1048
        static::unsetSessionVar('itrustuin');
1049
1050
        // Current skin
1051
        static::unsetSessionVar('cilogon_skin');
1052
    }
1053
1054
    /**
1055
     * unsetAllUserSessionVars
1056
     *
1057
     * This is a convenience method to clear all session variables related
1058
     * to the client and the user.
1059
     */
1060
    public static function unsetAllUserSessionVars()
1061
    {
1062
        static::unsetClientSessionVars();
1063
        static::unsetUserSessionVars();
1064
    }
1065
1066
    /**
1067
     * verifySessionAndCall
1068
     *
1069
     * This function is a convenience method called by several cases in the
1070
     * main 'switch' call at the top of the index.php file. I noticed
1071
     * a pattern where verifyCurrentUserSession() was called to verify the
1072
     * current user session. Upon success, one or two functions were called
1073
     * to continue program, flow. Upon failure, cookies and session
1074
     * variables were cleared, and the main Logon page was printed. This
1075
     * function encapsulates that pattern. If the user's session is valid,
1076
     * the passed-in $func is called, possibly with parameters passed in as
1077
     * an array. The function returns true if the session is verified, so
1078
     * that other functions may be called upon return.
1079
     *
1080
     * @param function $func The function to call if the current session is
0 ignored issues
show
Bug introduced by
The type CILogon\Service\function was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1081
     *        successfully verified.
1082
     * @param array $params (Optional) An array of parameters to pass to the
1083
     *        function. Defaults to empty array, meaning zero parameters.
1084
     */
1085
    public static function verifySessionAndCall($func, $params = array())
1086
    {
1087
        $retval = false;
1088
        if (Content::verifyCurrentUserSession()) { // Verify PHP session is valid
1089
            $retval = true;
1090
            call_user_func_array($func, $params);
1091
        } else {
1092
            printLogonPage(true); // Clear cookies and session vars too
0 ignored issues
show
Bug introduced by
The function printLogonPage was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1092
            /** @scrutinizer ignore-call */ 
1093
            printLogonPage(true); // Clear cookies and session vars too
Loading history...
1093
        }
1094
        return $retval;
1095
    }
1096
1097
    /**
1098
     * isEduGAINAndGetCert
1099
     *
1100
     * This function checks to see if the current session IdP is an
1101
     * eduGAIN IdP (i.e., not Registered By InCommon) and the IdP does not
1102
     * have both the REFEDS R&S and SIRTFI extensions in metadata. If so,
1103
     * check to see if the transaction could be used to fetch a
1104
     * certificate. (The only time the transaction is not used to fetch
1105
     * a cert is during OIDC without the 'getcert' scope.) If all that is
1106
     * true, then return true. Otherwise return false.
1107
     *
1108
     * @param string $idp (optional) The IdP entityID. If empty, read value
1109
     *        from PHP session.
1110
     * @param string $idpname (optional) The IdP display name. If empty,
1111
     *        read value from PHP session.
1112
     * @return bool True if the current IdP is an eduGAIN IdP without
1113
     *         both REFEDS R&S and SIRTFI, AND the session could be
1114
     *         used to get a certificate.
1115
     */
1116
    public static function isEduGAINAndGetCert($idp = '', $idpname = '')
1117
    {
1118
        $retval = false; // Assume not eduGAIN IdP and getcert
1119
1120
        // If $idp or $idpname not passed in, get from current session.
1121
        if (strlen($idp) == 0) {
1122
            $idp = static::getSessionVar('idp');
1123
        }
1124
        if (strlen($idpname) == 0) {
1125
            $idpname = static::getSessionVar('idpname');
1126
        }
1127
1128
        // Check if this was an OIDC transaction, and if the
1129
        // 'getcert' scope was requested.
1130
        $oidcscopegetcert = false;
1131
        $oidctrans = false;
1132
        $clientparams = json_decode(static::getSessionVar('clientparams'), true);
1133
        if (isset($clientparams['scope'])) {
1134
            $oidctrans = true;
1135
            if (
1136
                preg_match(
1137
                    '/edu\.uiuc\.ncsa\.myproxy\.getcert/',
1138
                    $clientparams['scope']
1139
                )
1140
            ) {
1141
                $oidcscopegetcert = true;
1142
            }
1143
        }
1144
1145
        // First, make sure $idp was set and is not an OAuth2 IdP.
1146
        $idplist = static::getIdpList();
1147
        if (
1148
            ((strlen($idp) > 0) &&
1149
            (strlen($idpname) > 0) &&
1150
            (!in_array($idpname, static::$oauth2idps))) &&
1151
                (
1152
                // Next, check for eduGAIN without REFEDS R&S and SIRTFI
1153
                ((!$idplist->isRegisteredByInCommon($idp)) &&
1154
                       ((!$idplist->isREFEDSRandS($idp)) ||
1155
                        (!$idplist->isSIRTFI($idp))
1156
                       )
1157
                ) &&
1158
                // Next, check if user could get X509 cert,
1159
                // i.e., OIDC getcert scope, or a non-OIDC
1160
                // transaction such as PKCS12, JWS, or OAuth 1.0a
1161
                ($oidcscopegetcert || !$oidctrans)
1162
                )
1163
        ) {
1164
            $retval = true;
1165
        }
1166
        return $retval;
1167
    }
1168
}
1169