Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ContentSecurityPolicyHookHandler
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 3
156
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onContentSecurityPolicyDefaultSource
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
72
 onContentSecurityPolicyScriptSource
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\Extension\CentralAuth\Hooks\Handlers;
22
23use MediaWiki\Config\Config;
24use MediaWiki\Context\RequestContext;
25use MediaWiki\Extension\CentralAuth\CentralAuthHooks;
26use MediaWiki\Extension\CentralAuth\Config\CAMainConfigNames;
27use MediaWiki\Hook\ContentSecurityPolicyDefaultSourceHook;
28use MediaWiki\Hook\ContentSecurityPolicyScriptSourceHook;
29use MediaWiki\WikiMap\WikiMap;
30
31class ContentSecurityPolicyHookHandler implements
32    ContentSecurityPolicyDefaultSourceHook,
33    ContentSecurityPolicyScriptSourceHook
34{
35
36    private Config $config;
37
38    public function __construct( Config $config ) {
39        $this->config = $config;
40    }
41
42    /**
43     * Add other domains as CSP source if auto-login is going to be attempted
44     *
45     * This is adding domains for images (and other req types), not scripts.
46     *
47     * @note We can't do $out->getCSP()->addDefaultSrc in onBeforePageDisplay,
48     * because that hook runs after the header is already outputted.
49     * @param string[] &$defaultSrc Array of allowed CSP sources.
50     * @param array $policyConfig
51     * @param int $mode
52     */
53    public function onContentSecurityPolicyDefaultSource(
54        &$defaultSrc,
55        $policyConfig,
56        $mode
57    ) {
58        $out = RequestContext::getMain()->getOutput();
59        // So possibilities:
60        // * We are doing edge login because initial login was via API and this is next request.
61        // * We are doing edge login because JS loaded Special:CentralAutoLogin/start or /checkCookies
62        //   and user is logged in on a different wiki, which eventually loads edge html.
63        if (
64            !$out->getUser()->isRegistered() ||
65                $out->getRequest()->getSessionData( 'CentralAuthDoEdgeLogin' )
66        ) {
67            foreach ( CentralAuthHooks::getAutoLoginWikis() as $wikiID ) {
68                $wiki = WikiMap::getWiki( $wikiID );
69                $url = $wiki->getCanonicalServer();
70                if ( CentralAuthHooks::isMobileDomain() ) {
71                    $url = \MobileContext::singleton()->getMobileUrl( $url );
72                }
73                $defaultSrc[] = wfParseUrl( $url )['host'];
74            }
75        }
76
77        if ( !$out->getUser()->isRegistered() && $this->config->get( CAMainConfigNames::CentralAuthLoginWiki ) ) {
78            // For the non-js case, there is local image loaded, but it redirects to
79            // central wiki, so include it.
80            $loginWiki = WikiMap::getWiki( $this->config->get( CAMainConfigNames::CentralAuthLoginWiki ) );
81            $url = $loginWiki->getCanonicalServer();
82            if ( CentralAuthHooks::isMobileDomain() ) {
83                $url = \MobileContext::singleton()->getMobileUrl( $url );
84            }
85            $defaultSrc[] = wfParseUrl( $url )['host'];
86        }
87    }
88
89    /**
90     * Add other domains as CSP source if auto-login is going to be attempted
91     *
92     * This is adding domains for scripts but not images.
93     *
94     * This is basically for ext.centralauth.centralautologin and corresponds
95     * to self::getCentralautologinJsData
96     *
97     * @note We can't do $out->getCSP()->addScriptSrc() in onBeforePageDisplay,
98     * because that hook runs after the header is already outputted.
99     * @param string[] &$scriptSrc Array of allowed CSP sources.
100     * @param array $policyConfig
101     * @param int $mode
102     */
103    public function onContentSecurityPolicyScriptSource(
104        &$scriptSrc,
105        $policyConfig,
106        $mode
107    ) {
108        $out = RequestContext::getMain()->getOutput();
109        if ( $this->config->get( CAMainConfigNames::CentralAuthLoginWiki ) && !$out->getUser()->isRegistered() ) {
110            $loginWiki = WikiMap::getWiki( $this->config->get( CAMainConfigNames::CentralAuthLoginWiki ) );
111            $scriptSrc[] = wfParseUrl( $loginWiki->getCanonicalServer() )['host'];
112        }
113    }
114}