• Remember Mailing List

Re: Plone 3 Support

from Rob Miller on Aug 16, 2007 06:09 PM
Rob Campbell wrote:
> Rob Miller wrote:
>> ah, well, you must realize that the user will NOT have the Owner role 
>> at this point.  she's not logged in, she's trying to set her initial 
>> password.  any time the user goes through the PasswordResetTool 
>> process, she will be anonymous.
>>
>> i'm pretty sure this works already in Plone 2.5, although i don't 
>> remember exactly how it was handled.  and maybe it's broken and i just 
>> don't know it... :-P.  unfortunately, i don't have time to dig into it 
>> any further at the moment.  if i can, i'll take a look over the next 
>> few days to see what i can discover.
>>
>> -r
> 
> Ok, that would explain the error.  Would adding the Set own password 
> permission for Anonymous users fix it?

no.  at best it would do nothing (who is the "own" in "Set own password" for 
anonymous users, anyway), and at worst it would allow any anonymous user to 
change any other member's password.

> Would that cause security 
> problems allowing any Anonymous user to change any password?

it might.  :-).

anyway, i looked at the code a bit more and realized that it's not actually 
the password setting that's causing the problem.  the password is set in the 
uf.userSetPassword() call that happens on line 142; your failure is happening 
on line 151, on the following call:

member.setMemberProperties(dict(must_change_password=0))

this is trying to set the "must_change_password" property, to mark that the 
password change has happened already.

that field was just recently added to the remember schema 5 days ago:

http://dev.plone.org/collective/changeset/47063

before this was added, there was no problem w/ PasswordResetTool, b/c when it 
tried to set the value, it realized there was no AT field that matched that 
name and it just returned.  now that remember is supporting that field name, 
however, we've got a problem, b/c setProperties is doing an explicit security 
check and (of course) anonymous users are not showing up as having rights to 
change this value.

AFAICT, the only thing to do is to make a change to PasswordResetTool to work 
around remember's security checks.  this could possibly be done in PwRT 
itself, assuming the maintainer is okay w/ a remember-specific workaround in 
there, or we could monkeypatch it from remember (less that ideal).  in any 
event, i've included a diff (untested) to PasswordResetTool.py at the end of 
this message that should do the trick.

this is a bit of a recurring problem.  setProperties on the member object 
always explicitly checks permissions so that users can't use it to circumvent 
the AT security settings on member schema fields.  this often interferes with 
trusted code that wants to use this call, however.  AFAICT, there's no good 
way for setProperties to check and see whether or not the calling context is 
trustable, in the Zope sense.  there has to be a better way than putting 
security checks in all of the calling code, but i haven't found it yet.

-r



Index: PasswordResetTool.py
===================================================================
--- PasswordResetTool.py        (revision 47446)
+++ PasswordResetTool.py        (working copy)
@@ -9,6 +9,7 @@
  from OFS.SimpleItem import SimpleItem
  from Globals import InitializeClass, DTMLFile
  from AccessControl import ClassSecurityInfo
+from AccessControl import Unauthorized
  from Products.CMFCore.permissions import ManagePortal

  from interfaces.portal_password_reset import portal_password_reset as 
IPWResetTool
@@ -148,7 +149,12 @@
                  # (and stupid!) way to change a password in Zope
                  member.setSecurityProfile(password=password)

-        member.setMemberProperties(dict(must_change_password=0))
+        try:
+            member.setMemberProperties(dict(must_change_password=0))
+        except Unauthorized: # we're probably using remember
+            if member.aq_base.getattr('getField', None) is not None:
+                field = member.getField('must_change_password')
+                field.getMutator(member)(False)

          # clean out the request
          del self._requests[randomstring]

Return to date view: threaded or flat