Bug #34820

t3lib_befunc::getViewDomain does not respect http/https scheme

Added by Christian Nölle over 7 years ago. Updated 12 months ago.

Status:
Closed
Priority:
Must have
Assignee:
-
Category:
-
Target version:
-
Start date:
2012-03-14
Due date:
% Done:

100%

TYPO3 Version:
4.5
PHP Version:
5.3
Tags:
Complexity:
hard
Is Regression:
No
Sprint Focus:

Description

After yesterdays update bug http://forge.typo3.org/issues/30892 was fixed. But that introduced a problem for us:

We have a https BE, which uses a non public domain on a custom port, which serves a multidomain setup. After introduction of this bugfix page previews are rendered using the correct domain name for this particular page. BUT: the call is using the https scheme used in the backend and not http. There is no valid certificate for the public domains, only for the non public be domain, so this results in an error for the user with untrusted certificate.


Related issues

Related to TYPO3 Core - Bug #30892: t3lib_befunc::getViewDomain returns wrong or no domain Closed 2011-10-13
Related to TYPO3 Core - Feature #36542: Changed domain handling on "View webpage" from backend causes problems Closed 2012-04-25
Related to TYPO3 Core - Bug #39514: Page preview broken with lockSSL=1/2 and url_scheme=http Closed 2012-08-03
Related to TYPO3 Core - Bug #62129: It isn't posible to set the url scheme for a whole pagetree for preview Closed 2014-10-09
Duplicated by TYPO3 Core - Bug #35392: Preview links not working if BE is using SSL and websites aren't Closed 2012-03-30

Associated revisions

Revision ccf7dae5 (diff)
Added by Wouter Wolters about 4 years ago

[BUGFIX] Double protocol when using TCEMAIN.previewDomain

In EXT:viewpage the option TCEMAIN.previewDomain is used but
not evaluated correctly. The option can contain the protocol
already and this is not respected in EXT:viewpage.

Check if domain already contains a protocol.

Resolves: #34820
Resolves: #36542
Resolves: #23115
Releases: master, 6.2
Change-Id: I13f7cda1dca54d60d350ba460e43ec924c140d35
Reviewed-on: http://review.typo3.org/41095
Reviewed-by: Helmut Hummel <>
Tested-by: Helmut Hummel <>
Reviewed-by: Christian Kuhn <>
Tested-by: Christian Kuhn <>
Reviewed-by: Wouter Wolters <>
Tested-by: Wouter Wolters <>

Revision b438ca6d (diff)
Added by Wouter Wolters about 4 years ago

[BUGFIX] Double protocol when using TCEMAIN.previewDomain

In EXT:viewpage the option TCEMAIN.previewDomain is used but
not evaluated correctly. The option can contain the protocol
already and this is not respected in EXT:viewpage.

Check if domain already contains a protocol.

Resolves: #34820
Resolves: #36542
Resolves: #23115
Releases: master, 6.2
Change-Id: I13f7cda1dca54d60d350ba460e43ec924c140d35
Reviewed-on: http://review.typo3.org/41122
Reviewed-by: Wouter Wolters <>
Tested-by: Wouter Wolters <>
Reviewed-by: Christian Kuhn <>
Tested-by: Christian Kuhn <>

History

#1 Updated by Christian Nölle over 7 years ago

To clarify: None of the pages is configured using https scheme in BE.

#2 Updated by Oliver Hader over 7 years ago

  • Status changed from New to Needs Feedback
  • PHP Version set to 5.3

Did that work before the release of TYPO3 4.5.12 (which initially introduced the first regression on the preview link) - so how did it behave in TYPO3 4.5.11?

#3 Updated by Christian Nölle over 7 years ago

Yes, did work in 4.5.12 and prior.

Behaviour was: Preview link used the BE domain (with https/port scheme), first click on a link switched over to the domain respecting the domain record of the particular page (non https).

Note: the BE domain does not own a domain record in T3.

#4 Updated by Philipp Gampe over 7 years ago

@Oli IMHO this is a big blocker in case a server does not offer HTTPS on other domains at all!

#5 Updated by Oliver Hader over 7 years ago

@Christian: I see the problem, so basically your scenario defines a (valid) special case which requires an additional TSconfig property like "options.view.currentDomain" or "options.view.currentDomainIfUndefined" - thus, if your special "backend.domain.com" is not available in sys_domains, the current one is used

@Philipp: Is this the case, that HTTPS is not working at all?

#6 Updated by Christian Nölle over 7 years ago

Mh, well, that could be a solution. But wouldn't it be better to respect the http/https settings in page settings for a root (and sub-) pages of a website?

Concerning the comment of Philipp: Possible. Let me explain our setup a bit further: We are maintaining serveral backends on one (sort of ;)) machine using NameVirtualHosts from Apache. All BEs have SSL configured. To work around the issue of certificates missmatch, each VirtualHost (eg BE) has it's own SSL-Port (Restriction of NameVirtualHosts and many certs).

So https://backend_1.foo.bar:1234 holds the domain for bar.foo. Preview will generate a link as https://bar.foo (which will translate to https://bar.foo:443) But on port 443 a totally different host ist listing. Two problems: First the user is presented a certificate warning (as cert of different host is presented), second - if cert is accepted - user is getting a server error.

#7 Updated by Philipp Gampe over 7 years ago

Well, what I have in mind is this:

A backend at backend.example.org with SSL.
A domain record for frontent.example.org without SSL. That means the webserver does not support SSL and no service is listening on port 443.

So if the preview link now point to the https://frontent.example.org/, the user will get a server error or even "there is nothing" from his browser.

#8 Updated by Christian Nölle over 7 years ago

Yep, right. And as a surplus, we have the ports - set via conf vars - which should be respected as well.

#9 Updated by Christian Nölle over 7 years ago

Mh, with the release of 4.5.14 this is getting worse. As 4.5.14 is a security release, but https is not working correctly.

#10 Updated by Florian Seirer over 7 years ago

We have a similar setup, and I can confirm this behaviour.

I used the old version from https://review.typo3.org/#/c/9317/3/t3lib/class.t3lib_befunc.php, and page previewing works again.

#11 Updated by Sybille Peters over 7 years ago

We have a similar problem (see #36542) and I have patched class.t3lib_befunc.php in 4.5.15 update. But in the long run, this is not a good solution. Also, we soon plan to update to 4.6.

#12 Updated by Florian Seirer over 7 years ago

To get rid of this behaviour in 4.7.1, replace the function getViewDomain (class.t3lib_befunc.php, starting line 2647) with the following code.
Not sure if this is the best way to fix this issue, though.

public static function getViewDomain($pageId, $rootLine = NULL) {
$domain = rtrim(t3lib_div::getIndpEnv('TYPO3_SITE_URL'), '/');
if (!is_array($rootLine)) {
$rootLine = self::BEgetRootLine($pageId);
}
// checks alternate domains
if (count($rootLine) > 0) {
$urlParts = parse_url($domain);
if (self::getDomainStartPage($urlParts['host'], $urlParts['path'])) {
/** @var t3lib_pageSelect $sysPage */
$sysPage = t3lib_div::makeInstance('t3lib_pageSelect');
$page = (array)$sysPage->getPage($pageId);
$protocol = 'http';
if ($page['url_scheme'] t3lib_utility_Http::SCHEME_HTTPS || ($page['url_scheme'] 0 && t3lib_div::getIndpEnv('TYPO3_SSL'))) {
$protocol = 'https';
}
$domain = $protocol . '://' . self::firstDomainRecord($rootLine);
}
}
return $domain;
}

#13 Updated by Christian Nölle about 7 years ago

Well, yes, that is the old code, we use this as well right at the moment. I try to dig into this next week, try to create a patch for the new code, as this issue gets no publicity from core maintainers. Maybe some poorly coded code from me can get this going... :D

#14 Updated by Oliver no-lastname-given about 7 years ago

The following setup at our site relates to this bug but is independent from https or http:

The backend is reached by:
http://INTERNAL.host.name/ABC/typo3/backend.php

or https, it doesnt matter, because its only internal accessible.

The frontend (the regular webpage) URL is:
http://EXTERNAL.host.name/ABC/index.php?id=1

Again https would also work as all pages can be viewed using https.

Clicking in "View Webpage" in the backend will open the URL without the necessary part ABC:
http://EXTERNAL.host.name/index.php?id=1

As a temporary solution to this behaviour I reactivated the old version (4.5.11) of class.t3lib_befunc.php

Please put this up on the priority list as next update will have the same negative effect on my installation. Thanx in advance.

Oli

#15 Updated by Jörg Velletti over 6 years ago

For us it was the same Problem:

we have a multi Domain tree, one of them with https, the others ONLY with http.
Backend only available via https.

eavry preview link from a backend page to frontend ends up to a https URL on both pagetrees, as all pages are created in the past with URL_scheme = 0

.....................................
*i solved it this way: *

Set URL_Scheme of the ROOT Page of the spezific domain tree to: 1 (= "http://") insted of "0" = (unknown)
AND
changed the line:

$protocol = 'https';

against this 4 lines:

$rootpage = (array)$sysPage->getPage($rootLine[1]['uid']);
if ( $rootpage['url_scheme'] == 0 || $rootpage['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS ) {
    $protocol = 'https';
}

with this solution i can force https on each page separately by page properties OR set a default on rootpage ID

#16 Updated by Michael Stucki over 6 years ago

  • Status changed from Needs Feedback to Accepted
  • Complexity set to hard

Will need to look at this.

#17 Updated by Jörg Velletti over 6 years ago

@michi

sorry but i think the complexity is not so hard. for any questions you can contact me (in german or english)
http://forge.typo3.org/users/37422
and with some luck in the next 2 weeks i will get setup gerrit working to push my changes directly ..

or see the full changed function below

    public static function getViewDomain($pageId, $rootLine = NULL) {
        $domain = rtrim(t3lib_div::getIndpEnv('TYPO3_SITE_URL'), '/');

        if (!is_array($rootLine)) {
            $rootLine = self::BEgetRootLine($pageId);
        }
            // checks alternate domains
        if (count($rootLine) > 0) {
            $urlParts = parse_url($domain);
                /** @var t3lib_pageSelect $sysPage */
            $sysPage = t3lib_div::makeInstance('t3lib_pageSelect');

            $page = (array)$sysPage->getPage($pageId);
            $protocol = 'http';
            if ($page['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS || ($page['url_scheme'] == 0 && t3lib_div::getIndpEnv('TYPO3_SSL'))) {

                // j.v.: get url_scheme of Rootpage if actual page Settings url_scheme is 0 = undefined
                $rootpage = (array)$sysPage->getPage($rootLine[1]['uid']);

                // only change protokol to https if also on rootpage 'url_scheme' is set to https or is also undefinied like on actual page ..
                if ( $rootpage['url_scheme'] == 0 || $rootpage['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS ) {
                    $protocol = 'https';
                }
                // --- j.v. end of changes ..
            }

            $domainName = self::firstDomainRecord($rootLine);

            if ($domainName) {
                $domain = $domainName;
            } else {
                $domainRecord = self::getDomainStartPage($urlParts['host'], $urlParts['path']);
                $domain = $domainRecord['domainName'];
            }
            if ($domain) {
                $domain = $protocol . '://' . $domain;
            } else {
                $domain = rtrim(t3lib_div::getIndpEnv('TYPO3_SITE_URL'), '/');
            }
        }
        return $domain;
    }

#18 Updated by Michael Stucki about 6 years ago

Hello Jörg,

apparently, both of us didn't manage to continue with this issue...
Do you need any help in getting your Git environment to work? Let me know.

Greetings, Michael

#19 Updated by Christian Nölle about 6 years ago

Well, this should work, tested, but I got an logical error in that:

                // only change protokol to https if also on rootpage 'url_scheme' is set to https or is also undefinied like on actual page ..
                if ( $rootpage['url_scheme'] == 0 || $rootpage['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS ) {
                    $protocol = 'https';
                }

Why should I change to https when nothing is defined? It should only switch the protocol if:

  1. the rootpage or
  2. any other page I like to preview has https enabled

If there is no https enabled at the root page (or simply not selected) the above would switch to https, which would lead to same confusion as before.

                if ( $rootpage['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS ) {
                    $protocol = 'https';
                }

would be better for the rootpage. But it does not cover the case if rootpage is not-SSL and any subpage has SSL switched on? Or am I wrong?

#20 Updated by Jörg Velletti about 6 years ago

HI Christian

thanks for working on that issue and sorry for the late response as i was in vacation. To your question:

maybe there is still an issue for other enviroinments and after think about your remarks, i think "this" below will fit for all


 $protocol = 'http';
 if ($page['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS ) {
     // actual subpage Needs SSL, so we set it
     $protocol = 'https';      
} else if ($page['url_scheme'] == 0 && t3lib_div::getIndpEnv('TYPO3_SSL') ) {
     // actual Subpage has undefined scheme, but backend is using SSL so verify, if we need to set it
     $rootpage = (array)$sysPage->getPage($rootLine[1]['uid']);

     // only change protokol to https if also on rootpage 'url_scheme' is set to https 
     if ( rootpage['url_scheme'] == t3lib_utility_Http::SCHEME_HTTPS ) {
        $protocol = 'https';                  
     }
}

this will Our Needs, will not conflict with the Original settings before my changes and gives the redateur all possabilities he needs:
if backend is using SSL as it should be, the redakteur can set it for the subpages as he needs or if he does not need SSL just set it ONCE on Root page. only issue is left:

if he needs SSL on all Subpages but not on the Root page, then he needs to set SSL on all Subpages ...
but this can also be done by htaccess ...

#21 Updated by Georg Tiefenbrunn over 5 years ago

Hi Jörg!

I tried your solution and found that $rootpage = (array)$sysPage->getPage($rootLine[1]['uid']); does not check if 'is_siteroot' is set on a parent page. That's necessary for multidomain sites. Imagine following pagetree

TYPO3-Site (uid=0)
  + Websites (uid=1) 
    + Website A (uid=2)
      + Page A1 (uid=3)
      + Page A2 (uid=4)
      + ...
    + Website B (uid=5)
      + Page B1 (uid=6)
      + ...

Both websites use the same BE-url with SSL. 'is_siteroot' is set for pages uid 2 and 5. If Website A should use https and Website B normal http, 'url_scheme' for Website A (uid=2) must be set to 2 (https). If Page A2 (uid=4) is viewed, the use of https should be inherited from page uid=2.

I have no experience in TYPO3 BE coding and don't know if this could be achieved by the clause-param of function BEgetRootLine(). But as function getViewDomain() has an optional parameter $rootLine I decided to simply loop through the parent pages. My changes for 6.1.7 in typo3/sysext/backend/Classes/Utility/BackendUtility.php

-            if ($page['url_scheme'] == \TYPO3\CMS\Core\Utility\HttpUtility::SCHEME_HTTPS || $page['url_scheme'] == 0 && \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) {
-                $protocol = 'https';
-            }
+            if ($page['url_scheme'] == \TYPO3\CMS\Core\Utility\HttpUtility::SCHEME_HTTPS) {
+                // 'url_scheme' of page is explicitly set to SSL
+                $protocol = 'https';
+            } else if ($page['url_scheme'] == 0 && \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) {
+                // page has undefined 'url_scheme' and BE is using SSL: verify, if we need to set https
+                $rootPageUid = 0;
+                // if 'is_siteroot' is set on a parent page, use it as rootPage
+                foreach ($rootLine as $pageData) {
+                    if ($pageData['is_siteroot'] == TRUE) {
+                        $rootPageUid = $pageData['uid'];
+                        break;
+                    }
+                }
+                $rootPage = (array) $sysPage->getPage($rootPageUid);
+                // only change protocol to https if 'url_scheme' is set to https on rootPage
+                if ($rootPage['url_scheme'] == \TYPO3\CMS\Core\Utility\HttpUtility::SCHEME_HTTPS) {
+                    $protocol = 'https';
+                }
+            }

#22 Updated by Jörg Velletti over 5 years ago

Hi george

As i still stuck in 4.5.x LTS i just can say : thanks for porting this to 6.1. .. Your Solution looks fine for me.

But just to understand your Problem:

what page is delivered on your system if you are on uid 3 with:
$rootpage = (array)$sysPage->getPage($rootLine1['uid']);

is it uid 1 or uid 2 ?

i actually cant test your script because our domain setup is like this:

TYPO3-Site (uid=0)
  + Website A (uid=2) multilingual Single Tree with http Domains with .de .com .fr etc ...
     + Page A1 (uid=3)
     + Page A2 (uid=4)
     + ...
  + Website B (uid=5) multilingual https Domain with .com/de .com/en .com/fr etc .. = used for SSL backend 
     + Page B1 (uid=6)
     + ...
  + Website C (uid=7)
     + Page C1 (uid=8) multilingual https sub Domain with .com/de .com/en .com/fr etc ..
     + ...

so i will always get correctly :
uid 2 if on page 3 or 4,
uid 5 on uid 6
and uid 7 on uid 8

you can also contact me directly via email jVelletti [ at] nemetschek.com (in german or if needed in englisch)

#23 Updated by Georg Tiefenbrunn over 5 years ago

Hi Jörg!

I just rechecked everything on my setup. It's something like:

TYPO3-Site (uid=0)
  + Root (uid=200)
    + Global Records (uid=100)
      + Categories
      + Media
      + ...
    + Websites (uid=1)
      + Website A (uid=2)
        + Page A1 (uid=3)
        + Page A2 (uid=4)
        + ...
      + Website B (uid=5)
        + Page B1 (uid=6)
        + ...
      + Website C (uid=7)
        + Page C1 (uid=8)
        + ...

So I have two extra levels. Nevertheless $rootpage = (array)$sysPage->getPage($rootLine[1]['uid']); always returns uid 200 (Root). Seems as if this is an 6.x isue.

#24 Updated by Christian Nölle almost 5 years ago

Is there any news on this issue...Still patching manually... :/

#25 Updated by Sybille Peters over 4 years ago

Same here. Still patching manually for 4.5 and working on patch for 6.2.

#26 Updated by Jan Kornblum over 4 years ago

A solution where the rootline is beeing respected for the "url_scheme" really would be fine!

#27 Updated by Wouter Wolters over 4 years ago

  • Status changed from Accepted to Needs Feedback
  • Is Regression set to No

Hi, there is an undocumented FEATURE to set an alternative previewDomain in PageTSConfig.

TCEMAIN.viewDomain = example.com

If you have your backend running on https and your frontend not you can specify a protocol in this setting.

TCEMAIN.viewDomain = http://example.com

Does this solve the problem?

#28 Updated by Jörg Velletti over 4 years ago

thanks for the hint, but in my opinion it does not help:

the Function that reads this Value should expect a domainname WITHOUT Protokol (as firstDmianRecord also is stored without Protocol) and at least Domain Name and protocol is copied together.

so your example will generate http://http://example.com :

see the core code ..

****
protected function getDomainName($pageId) {
$previewDomainConfig = $GLOBALS['BE_USER']->getTSConfig('TCEMAIN.previewDomain', BackendUtility::getPagesTSconfig($pageId));
if ($previewDomainConfig['value']) {
$domain = $previewDomainConfig['value'];
} else {
$domain = BackendUtility::firstDomainRecord(BackendUtility::BEgetRootLine($pageId));
}


protected function getTargetUrl() {
... cut some lines ...

// Modify relative path to protocol with host if domain record is given
$protocolAndHost = '..';
if ($domainName) {
$protocol = 'http';
$page = (array) $sysPage->getPage($finalPageIdToShow);
if ($page['url_scheme'] 2 || $page['url_scheme'] 0 && \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) {
$protocol = 'https';
}
$protocolAndHost = $protocol . '://' . $domainName;
}

#29 Updated by Gerrit Code Review about 4 years ago

  • Status changed from Needs Feedback to Under Review

Patch set 1 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at http://review.typo3.org/41095

#30 Updated by Gerrit Code Review about 4 years ago

Patch set 2 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at http://review.typo3.org/41095

#31 Updated by Gerrit Code Review about 4 years ago

Patch set 1 for branch TYPO3_6-2 of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at http://review.typo3.org/41122

#32 Updated by Wouter Wolters about 4 years ago

  • Status changed from Under Review to Resolved
  • % Done changed from 0 to 100

#33 Updated by Benni Mack 12 months ago

  • Status changed from Resolved to Closed

Also available in: Atom PDF