Hi,

On 2025/03/07 1:50, Chris Shelton wrote:
> After working through a plan to upgrade an old Trac installation from version 
> 0.12 to 1.6, due to the need to shift to python 3, I believe I have 
> discovered an issue with how Python 3 is parsing cookies when they are 
> "invalid" cookies present for a session.  
> 
> First of all, I have made a small change to the code of trac/web/auth.py that 
> seems to work for my environment where the entire Trac installation requires 
> authentication to access.  Trac receives the REMOTE_USER information from 
> wsgi, but the trac_auth cookie may not be set on a user's initial login.  My 
> code change is in the authenticate function:
> 
> --- auth.py.orig        2025-03-04 17:46:22.942392186 -0500
> +++ auth.py     2025-03-05 16:59:47.074857014 -0500
> @@ -91,13 +91,28 @@
> 
>      def authenticate(self, req):
>          authname = None
> +        # following added by cshelton - 1/22/2025
> +        self.env.log.debug("in authenticate function")
>          if req.remote_user:
>              authname = req.remote_user
> +            self.env.log.debug("REMOTE_USER is copied to authname as %s", 
> authname)
> +            self.env.log.debug("request cookies are %s", req.incookie.output)
> +            if not 'trac_auth' in req.incookie:
> +                self.env.log.debug("no trac_auth cookie found, so empty 
> authname and return None")
> +                return None
> +
>          elif 'trac_auth' in req.incookie:
>              authname = self._get_name_for_cookie(req,
>                                                   req.incookie['trac_auth'])
> +            self.env.log.debug("found trac_auth cookie")
> 
>          if not authname:
> +            self.env.log.debug("authname not set, returning None")
>              return None
> 
>          if self.ignore_case:
> 
> This change causes the authenticate function to return None if the 
> remote_user is set, but there is not a trac_auth cookie present.  This 
> triggers the noanonymousplugin to redirect the request to /trac/login, to set 
> the trac_auth cookie, then redirects back to the page the user was trying to 
> access.  
> 
> This setup has been working well for several years with my Trac 0.12 
> installation, but has been inconsistent with Trac 1.6.  After much 
> frustration, I finally discovered this issue reported by the Django project:
> https://code.djangoproject.com/ticket/26158 
> <https://code.djangoproject.com/ticket/26158>
> The issue that I am having is very similar to this one, in that there are 
> several cookies regularly set by a large ERP system used by my organization 
> that are presented to my Trac installation.  There is at least one invalid or 
> unnamed cookie set at a higher level (.iu.edu <http://iu.edu>), while my Trac 
> installation runs at a subdomain (.prvt.controller.iu.edu 
> <http://prvt.controller.iu.edu>).  
> 
> When I remove the cookies for the .iu.edu <http://iu.edu> domain, or when 
> running Trac in an incognito window, it behaves normally.  But when the 
> .iu.edu <http://iu.edu> cookies are present, Trac (or really Python) fails to 
> parse any cookies at all, leading to a redirect loop when trying to initially 
> login.  The Django project ticket noted that python 3 will fail to parse any 
> cookies at all when only one invalid cookie is found.  Their workaround for 
> this issue was to write their own cookie parsing routine, and remove 
> references to SimpleCookie and BaseCookie:
> https://github.com/django/django/commit/93a135d111c2569d88d65a3f4ad9e6d9ad291452
>  
> <https://github.com/django/django/commit/93a135d111c2569d88d65a3f4ad9e6d9ad291452>
> 
> Would it be possible to implement a similar fix for Trac to manually parse 
> cookies instead of relying on the python3 cookie code that seems to discard 
> all cookies if only one cookie is "bad"?  I am tempted to try to implement a 
> similar change in Trac as the Django project, but my python coding skills 
> need some improvement.  
> 
> Thanks for any advice regarding how to best implement a fix for this issue.
> 
> Chris

Thanks for the investigating.

I tested how Google Chrome and Firefox behave with such unnamed cookies: the 
browsers don't ignore such cookies, but send them to the server.

I think this is an issue of http.cookies in Python, but it doesn't look like it 
will be fixed soon.... I consider that Trac should add work around for it.

Could you please create new ticket for the issue on https://trac.edgewall.org?

Quick fix:

[[[
diff --git a/trac/web/api.py b/trac/web/api.py
index 7f8b59bdc..fa888f0b0 100644
--- a/trac/web/api.py
+++ b/trac/web/api.py
@@ -612,7 +612,13 @@ class RequestDone(TracBaseError):


 class Cookie(SimpleCookie):
+
+    _separator_re = re.compile(r'\s*;\s*', re.ASCII)
+
     def load(self, rawdata, ignore_parse_errors=False):
+        # Remove unnamed cookies
+        rawdata = '; '.join(item for item in self._separator_re.split(rawdata)
+                                 if '=' in item)
         if ignore_parse_errors:
             self.bad_cookies = []
             self._BaseCookie__set = self._loose_set
]]]

-- 
Jun Omae <[email protected]> (大前 潤)

-- 
You received this message because you are subscribed to the Google Groups "Trac 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/trac-users/3f6248a8-8519-4b40-ad14-8c5733144c18%40gmail.com.

Reply via email to