Bug #34820
closedt3lib_befunc::getViewDomain does not respect http/https scheme
Added by Christian Nölle over 12 years ago. Updated about 6 years ago.
100%
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.
Updated by Christian Nölle over 12 years ago
To clarify: None of the pages is configured using https scheme in BE.
Updated by Oliver Hader over 12 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?
Updated by Christian Nölle over 12 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.
Updated by Philipp Gampe over 12 years ago
@Oli IMHO this is a big blocker in case a server does not offer HTTPS on other domains at all!
Updated by Oliver Hader over 12 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?
Updated by Christian Nölle over 12 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.
Updated by Philipp Gampe over 12 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.
Updated by Christian Nölle over 12 years ago
Yep, right. And as a surplus, we have the ports - set via conf vars - which should be respected as well.
Updated by Christian Nölle over 12 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.
Updated by Florian Seirer over 12 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.
Updated by Sybille Peters over 12 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.
Updated by Florian Seirer over 12 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;
}
Updated by Christian Nölle over 12 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
Updated by Anonymous over 12 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
Updated by Jörg Velletti over 11 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
Updated by Michael Stucki over 11 years ago
- Status changed from Needs Feedback to Accepted
- Complexity set to hard
Will need to look at this.
Updated by Jörg Velletti over 11 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; }
Updated by Michael Stucki over 11 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
Updated by Christian Nölle over 11 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:
- the rootpage or
- 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?
Updated by Jörg Velletti about 11 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 ...
Updated by Georg Tiefenbrunn almost 11 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'; + } + }
Updated by Jörg Velletti almost 11 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)
Updated by Georg Tiefenbrunn almost 11 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.
Updated by Christian Nölle almost 10 years ago
Is there any news on this issue...Still patching manually... :/
Updated by Sybille Peters almost 10 years ago
Same here. Still patching manually for 4.5 and working on patch for 6.2.
Updated by Jan Kornblum almost 10 years ago
A solution where the rootline is beeing respected for the "url_scheme" really would be fine!
Updated by Wouter Wolters over 9 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?
Updated by Jörg Velletti over 9 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;
}
Updated by Gerrit Code Review over 9 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
Updated by Gerrit Code Review over 9 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
Updated by Gerrit Code Review over 9 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
Updated by Wouter Wolters over 9 years ago
- Status changed from Under Review to Resolved
- % Done changed from 0 to 100
Applied in changeset ccf7dae56adaae36f4c0a103f1c7b3c17af8494a.