Edgewall Software

Ticket #2553 (closed defect: fixed)

Opened 3 years ago

Last modified 11 months ago

tracd reverts to http:// after a POST even if stunnel is being used via a https:// url.

Reported by: anonymous Owned by:
Priority: high Milestone: 0.10.5
Component: web frontend/tracd Version: devel
Severity: major Keywords: tracd https stunnel mod_proxy patch apache mod_python
Cc: jorge.vargas@…

Description (last modified by cboos) (diff)

Running tracd through stunnel, I access trac via a  https://url/trac. Everything works fine until I change something (confirm a wiki edit, add a new ticket, login, etc.) and the url forwards to  http://url/trac instead of https.

To fix this, I changed the self.scheme = 'http' in TracHTTPRequest in standalone.py to self.scheme='https'. But I imagine this should autodetect in some way.

Status for this issue

This is a problem affecting Trac up to and including 0.10.4.

In current 0.10.5dev and 0.11dev (b1, b2, rc1), there's a new setting in the TracIni#trac-section, use_base_url_for_redirect: when set to true, Trac will use the value set for base_url in the same .ini section as the actual target for the redirects, so you can set it to https://... if you really have no other choices. See also #6013.

Attachments

base_url.patch Download (0.6 KB) - added by cmlenz 3 years ago.
Use base_url when computing absolute URL of redirection
https_post_redirect2.patch Download (1.0 KB) - added by pkoelle@… 3 years ago.
honor base_url in Request.redirect()

Change History

  Changed 3 years ago by cboos

  • owner changed from jonas to cboos
  • status changed from new to assigned
  • description modified (diff)
  • milestone set to 0.9.4

One could use the Referer: header, if present.

Index: standalone.py
===================================================================
--- standalone.py       (revision 2721)
+++ standalone.py       (working copy)
@@ -325,21 +325,22 @@
         Request.__init__(self)
         self.__handler = handler
         self.__status_sent = False
-
-        self.scheme = 'http'
+        headers = handler.headers
+        self.scheme = 'http' # as default, but use Referer: header if
present
+        if headers.has_key('Referer'):
+            self.scheme = headers['Referer'].split(':')[0]
         self.method = self.__handler.command
         self.remote_addr = str(self.__handler.client_address[0])
         self.server_name = self.__handler.server.server_name
         self.server_port = self.__handler.server.server_port
-        if self.__handler.headers.has_key('Cookie'):
-            self.incookie.load(self.__handler.headers['Cookie'])
+        if headers.has_key('Cookie'):
+            self.incookie.load(headers['Cookie'])
         self.cgi_location = '/' + project_name
         self.idx_location = '/'
         environ = {'REQUEST_METHOD': self.method,
                    'QUERY_STRING': query_string}
-        headers = self.__handler.headers
         if self.method in ('GET', 'HEAD'):
             headers = None
         self.args = TracFieldStorage(self.__handler.rfile,
environ=environ,

Thoughts?

  Changed 3 years ago by anonymous

That fix works for my situation. Thanks!

  Changed 3 years ago by cmlenz

This is not that great a solution. The primary problem is that the referer could be a totally different site… for example, some site running over HTTPS that is linking a Trac site somewhere else. So at least, we should be checking whether the URL in the referer is pointing to the same host and base path before setting the scheme to https. But even then, I feel that this change is too much of a hack. Can you please try whether setting the base_url option in [wiki:TracIni trac.ini] also fixes the problem (without the patch above)?

[trac]
base_url = https://example.org/trac/

  Changed 3 years ago by anonymous

no, that fix does not work-- I reverted standalone.py to the 0.9.2 version and added your line in my trac_env/conf/trac.ini file -- doesn't work, same problem. I don't see the problem with the referrer approach- when would a non-trac referrer make a POST to update something within trac?

  Changed 3 years ago by cmlenz

Can you please try the attached base_url.patch?

  Changed 3 years ago by anonymous

With that base_url.patch + adding base_url to trac.ini and the original standalone.py from 0.9.2, it works. Thanks

Changed 3 years ago by cmlenz

Use base_url when computing absolute URL of redirection

  Changed 3 years ago by brian whitman <trac_bwhitman@…>

Relatedly, I put a tutorial  here on how to set up stunnel with trac with a link back to this ticket for the necessary patch.

  Changed 3 years ago by anonymous

I'm running trac with apache2 and I also have this probleem. This apache only listens to port 443. When I post something (like a ticket, wiki edit, ...) then I get redirect to the non https url. This results in 404. I used the patch attachted to this ticket and it works like a charm now. My config file has now two times the same config value. One time 'project.url' and one time the new 'trac.base_url'. Is this really needed? I run trac 0.9.2 from debian unstable.

  Changed 3 years ago by cboos

cmlenz: should I commit your attachment:base_url.patch Download?

  Changed 3 years ago by cboos

I guess yes... did so in r2820.

Should I port this to stable?

  Changed 3 years ago by cmlenz

sure

  Changed 3 years ago by cboos

  • status changed from assigned to closed
  • resolution set to fixed

Ported in r2830.

  Changed 3 years ago by anonymous

  • keywords multirepository added; stunnel removed
  • status changed from closed to reopened
  • resolution fixed deleted

I'm using Trac 0.9.4 on Debian etch, apache2, mod_python,  https://URL/. I'm using multiple repositories. When I select repository trac redirect me to  http://. Then I have to rewrite  http:// to  https:// from this point work well. I have also problem with login, but I'm not sure if this same problem.

  Changed 3 years ago by coderanger

  • status changed from reopened to closed
  • resolution set to fixed

Please open a new ticket, as that problem is unrelated to this one.

  Changed 3 years ago by JayJ

That fix works for me..  http://actgeoeng.mod.net.au

  Changed 3 years ago by irefuse [at] gmail [dot] com

  • status changed from closed to reopened
  • priority changed from normal to high
  • version changed from 0.9.2 to devel
  • milestone changed from 0.9.4 to 0.10
  • keywords stunnel added; multirepository removed
  • resolution fixed deleted

im running 0.10 and have my base_url set to the https: address of my trac yet when i make any kind of post it still redirects to http: and i dont understand why...this fix was supposed to have been commited as of 0.9.2 correct?

  Changed 3 years ago by irefuse [at] gmail [dot] com

i was looking at the source for stable and it looks like that section of the code still has the fix for this yet on trunk, the code is completely different and there looks like there isnt even a check for base_url anywhere in it. i dont really know python but it really doesnt look like there is any check for it.

  Changed 3 years ago by irefuse [at] gmail [dot] com

  • severity changed from normal to major

well i reread the original post of this ticket and noticed that the person who submitted this changed the self.scheme to use https... so i went looking through wsgi and found a similar set of lines of code:

environ['wsgi.url_scheme'] = 'http'
if environ.get('HTTPS', '').lower() in ('yes', 'on', '1'):
    environ['wsgi.url_scheme'] = 'https'

now, it looks to me like this should check to see if the environment is using https and set the scheme to https...but it's not doing a very good job because if i have my environment using https (with the base_url set to my https address) it doesnt use https when POSTing changes such as wiki modifications and such...i change the line:

environ['wsgi.url_scheme'] = 'http'

to

environ['wsgi.url_scheme'] = 'https'

and now everything works fine and dandy..i think there's something wrong with that wsgi check for https there...

  Changed 3 years ago by cmlenz

If you submit a form from an HTTPS address, Trac POSTs to an HTTPS address. Only after the POST we do a redirect (and only if the submission was completed successfully).

If Trac doesn't POST to an HTTPS address for you, something's really weird.

  Changed 3 years ago by cmlenz

… because the POST uses a server-relative URL (not including the protocol), but the redirect uses an absolute URL (including the protocol).

  Changed 3 years ago by cmlenz

See also #3208.

  Changed 3 years ago by anonymous

so where exactly would i put something similar to "SetEnv HTTPS 1" if im not using apache, but tracd with stunnel?

  Changed 3 years ago by cboos

  • status changed from reopened to new
  • milestone 0.10 deleted

I have not really the time to investigate on that one, so if someone wants to take over, he's more than welcome...

  Changed 3 years ago by cboos

  • owner cboos deleted

  Changed 3 years ago by cboos

  • milestone set to 0.10.4

See also #3381.

  Changed 3 years ago by pkoelle@…

  • keywords mod_proxy added

Got the same problem with tracd running begind apache with mod_proxy. From the outside, all projects are  https:// but communication between apache and tracd is plain http.

My reasoning would be: If base_url is set, the user knows what she's doing. So Request.redirect() should check base_url for the scheme and host part and fall back to wsgi.url_scheme and server_name when building url from a relative URL...

DISCLAIMER: I'm not very familiar with trac internals ;)

--- trac/web/api.py	2006-12-12 19:44:08.000000000 +0100
+++ /usr/lib/python2.4/site-packages/trac/web/api.py	2006-12-21 05:30:15.000000000 +0100
@@ -325,10 +325,14 @@
 
         self.send_response(status)
         if not url.startswith('http://') and not url.startswith('https://'):
-            # Make sure the URL is absolute
-            url = urlparse.urlunparse((self.scheme,
-                                       urlparse.urlparse(self.base_url)[1],
-                                       url, None, None, None))
+            # Make sure the URL is absolute, honor base_url for
+            # scheme and host if present
+            scheme, host, path, params, query, fragment = urlparse.urlparse(
+                                                                self.base_url)
+            if not scheme: scheme = self.scheme
+            if not host: host = self.server_name
+            url = urlparse.urlunparse((scheme, host, url, None, None, None))                           
+
         self.send_header('Location', url)
         self.send_header('Content-Type', 'text/plain')
         self.send_header('Pragma', 'no-cache')

  Changed 3 years ago by cboos

  • keywords patch added

  Changed 3 years ago by pkoelle@…

I have further investigated the situation (0.10.2):

  • client (https) -> apache with mod_proxy (http) -> tracd(localhost)
  • redirects after POST is fine out of the box for both http and https if base_url is NOT set.
  • If base_url is not set, X-Trac-Ticket-URL header for email notifications points to  http://localhost:8000/ticket/xxx. It could (partially) fixed by setting "ProxyPreserveHost? On" from apache but this breaks https redirects on POST again (why on earth?) and the scheme is still wrong.
  • If base_url is set, X-Trac-Ticket-URL is correct but this breaks POST redirects, a restart of tracd is needed after deleting base_url.

I thought there should be a less intrusive patch, i.e fixing this in the TicketNotifyEmail? class. However, the reason X-Trac-Ticket-URL is wrong if base_url is not set is in Request.init() when Request.abs_href is calculated from base_url OR Request._reconstruct_url(). There is no way to get the correct scheme and host in _reconstuct_url() so base_url is needed and I think my patch makes Request.redirect() behave like Request.init wrt using base_url.

A slightly simpler patch (against 0.10.3):

--- trac/web/api.py	2006-12-12 19:44:08.000000000 +0100
+++ /usr/lib/python2.4/site-packages/trac/web/api.py	2006-12-21 07:07:33.000000000 +0100
@@ -325,10 +325,12 @@
 
         self.send_response(status)
         if not url.startswith('http://') and not url.startswith('https://'):
-            # Make sure the URL is absolute
-            url = urlparse.urlunparse((self.scheme,
-                                       urlparse.urlparse(self.base_url)[1],
-                                       url, None, None, None))
+            # Make sure the URL is absolute, honor base_url for
+            # scheme and host if present
+            scheme, host, path, params, query, fragment = urlparse.urlparse(
+                                                              self.abs_href())
+            url = urlparse.urlunparse((scheme, host, url, None, None, None))                           
+
         self.send_header('Location', url)
         self.send_header('Content-Type', 'text/plain')
         self.send_header('Pragma', 'no-cache')

Changed 3 years ago by pkoelle@…

honor base_url in Request.redirect()

  Changed 2 years ago by jorge.vargas@…

  • cc jorge.vargas@… added
  • keywords apache mod_python added

Hi I got the following setup

2 apache instances on a shared machine, one is system the second is on my home running mod_python, and I had the same issue described below in the ticket it "sometimes" reverted back to http.

I have applied pkoelle's patch and it seems to work fine.

original post here  http://groups.google.com/group/trac-users/browse_thread/thread/4ebb6cd6555ec2e?hl=en

  Changed 2 years ago by Blindauer Emmanuel

I confirm that the patch https_post_redirect2.patch works fine for 10.3

  Changed 2 years ago by cboos

#3207 and #3208 closed as duplicates. The latter explains why using HTTPS environment variable is not reliable. That would explain why the patch above works.

  Changed 2 years ago by cboos

#4532 closed as duplicate. See also #5064, which explains why we shouldn't always use the configured data to reconstruct the URL.

  Changed 2 years ago by cboos

#5454 was closed as duplicate.

  Changed 2 years ago by cboos

  • status changed from new to closed
  • resolution set to fixed

pkoelle's patch applied in r5642 (trunk) and r5644 (0.10-stable).

Thanks for the patch and thanks to those who provided testing feedback.

  Changed 22 months ago by egbonme

  • status changed from closed to reopened
  • resolution fixed deleted

Hi, I may be missing something but it does not work for me. I just checked 0.10-stable out, which contains the above patches (right?), and a New Ticket submission reverts to a http:// URL instead of a https.

I'm using trac-0.10-stable (r6009) with stunnel 3.26 on a Ubuntu dapper Linux.

  Changed 22 months ago by cboos

What's your [trac] base_url setting in TracIni?

  Changed 22 months ago by egbonme

empty; is it a problem?

follow-up: ↓ 39   Changed 22 months ago by cboos

  • status changed from reopened to closed
  • resolution set to fixed

Currently it is problematic, yes. In trunk, that setting is mandatory in general, and in 0.10-stable it's mandatory in your situation (set the base_url to  https:// something). But we're still looking into improving the situation, see #5064.

I'm re-closing this as fixed, as at least the specific use case described here works well with the current code and setting.

in reply to: ↑ 38   Changed 21 months ago by egbonme

Replying to cboos:

Currently it is problematic, yes. In trunk, that setting is mandatory in general, and in 0.10-stable it's mandatory in your situation

Thanks. BTW I think it would be useful to also mention the base_url setting in STunnelTracd explicitly.

  Changed 13 months ago by cboos

  • description modified (diff)

Summarizing current status of the issue, after marking #7307 as duplicate.

  Changed 13 months ago by sbwoodside@…

Thanks cboos. I just upgraded to 0.11rc1 (see #7307) and my https redirects broke. Yes, I use tracd running behind a proxy, I would think this is a common configuration, considering that virtually all Ruby on Rails projects use this configuration.

Can you make a note of this in the docs for 0.11rc1 or 2 or whatever please, it broke when I upgraded and googling did not help me find this fix.

  Changed 11 months ago by mail@…

It seems the problem I'm currently facing is related to this bug too: I have the following Apache configuration:

<Location /project/trac>
        SetHandler mod_python
        PythonInterpreter main_interpreter
        PythonHandler trac.web.modpython_frontend
        PythonOption TracEnv /var/lib/trac/project
        PythonOption TracUriRoot /project/trac
        PythonOption Https 1
</Location>
<Location /project>
        RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule (.*) https://mydomain.com%{REQUEST_URI}
</Location>

This means, all requests going to  http://mydomain.com/project or  http://mydomain.com/project/trac should be redirected to  https:// ....

As long as I don't have the SSL rewrite configuration enabled, trac works fine, but as soon as I enable it, the requests go to the htdocs dir, where nothing is found, instead of being done by mod_python.

I've set base_url in trac.ini to  https://mydomain.com/project/trac, but it didn't change anything at all.

The version I'm using is 0.11 from Gentoo, built with USE="cgi mysql sqlite subversion vhosts -fastcgi -postgres".

Add/Change #2553 (tracd reverts to http:// after a POST even if stunnel is being used via a https:// url.)

Author


E-mail address and user name can be saved in the Preferences.


Change Properties
<Author field>
Action
as closed
Next status will be 'reopened'
to The owner will change from (none). Next status will be 'closed'
 
Note: See TracTickets for help on using tickets.