| Commit message (Collapse) | Author | Age | Files | Lines |
| | |
|
| | |
|
| |
|
|
|
|
|
|
| |
cookie problem. We can't use the Cookie module to parse the cookie
because it's too strict in what it accepts. Parse it ourselves using
re.split().
Should close SF bug # 664466.
|
| |
|
|
| |
exception that can get raised.
|
| |
|
|
|
|
|
|
| |
mailman-developers. There's an inconsistent use of the MemberAdaptor
API -- authenticateMember() is never called. This change seems to
work just fine.
Also: whitespace normalization.
|
| |
|
|
|
|
|
|
|
| |
a TypeError if its second argument contains null bytes. I have a hard
time understanding how that could happen, but it must be related to a
MM2.0.x upgrade.
This patch should fix the problem by catching and ignoring the
TypeError, which is equivalent to a failed challenge.
|
| |
|
|
| |
catch it and return false.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
The latter broke the upgrade script when upgrading from MM2.1a2 to
current cvs. This is because bin/update imports Mailman.MailList
which imports Mailman.SecurityManager which, if /that/ tries to
from...import...as will fail with an import error since there's still
a residual old Cookie.py laying around that doesn't have a
SimpleCookie class.
Once bin/update does its thing and gets rid of Mailman/Cookie.py{,c}
we're safe, but for now this is the best way to worm around the
problem.
|
| |
|
|
|
| |
site password, and we're doing AuthSiteAdmin, then issue a secret/key
combination that allows the site password to be cookie-fied.
|
| |
|
|
|
|
|
|
|
|
|
| |
class to decode the cookie data so there's no possibility of
unpickling exploits of untrusted data.
I'm still mildly concerned about using marshal.loads() to de-serialize
the cookie data we want to use for authorization, although I think
we're more or less safe for the reasons described in the preceding
comment. I should probably think about this some more, possibly using
the newly documented pickle anti-exploit measures.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
characters in keys, and it complains about the `@' signs in the
email addresses of AuthUser keys. So we'll obscure the email
address, changing `@' to `--at--', which contains only happy
characters.
This doesn't affect auto-guessing of the user based on the
presence of the cookie, because we just need to unobscure whatever
follows the `user+' prefix.
WebAuthenticate(): MMNotAMemberError -> NotAMemberError
MakeCookie(): Raise ValueError instead of MMBadUserError.
CheckCookie(): The prefix for AuthUser is listname+user+, and here's
where we unobscure anything we've found.
|
| |
|
|
|
|
|
|
| |
the key. It's strictly interpreting the relevant RFC. We may
change Cookie.py to be more relaxed, but instead of trying to
maintain our own copy of this file, we'll just change the
separator to be a `+' intead of a `:' -- Cookie.py seems happy
with this.
|
| | |
|
| |
|
|
|
| |
__checkone(): Likewise, if the secret isn't a string, return 0
(i.e. no the user isn't authenticated).
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
zero arguments, so we remove the crypted_password parameter. This
means that self.password will be set in MailList instead.
AuthContextInfo(): Instead of getting the user password directly out
of self.passwords, use the API method getMemberPassword() -- which
itself raises MMNotAMemberError if the user isn't a member of the
list.
ChangeUserPassword(): Removed. Use the new setMemberPassword() API
method.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
AuthContextInfo(): Allow `user' argument to be optional; default to
None.
Authenticate(): Re-install backwards compatibility for pre-MM2.1 list
passwords. For AuthListAdmin context only, if the sha check fails,
fallback to crypt (if the crypt module could be imported) and md5
checks. If either of the latter two matches, assume that the list
password is "old style" and auto-upgrade it to the sha password, based
on the matching plain text response. This way, MM2.0.x list passwords
won't just be broken upon an upgrade.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
is false, then scan the cookie keys for user names. This is used in
private archive authentication (which doesn't have a user context in
the url), so that if a user has already authenticated to edit their
options, they get into the private archives with no login necessary.
Note that this does /not/ open a hole for user option pages because
those have a user context in the url which is passed to CheckCookie
and must match explicitly.
__checkone(): Does one authcontext/user authentication.
|
| |
|
|
|
| |
in a temporary variable and check that variable against the secret
(this is so that subsequent checks have the raw password).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
authorization contexts and the roles of User, List Owner, List
Moderator, (List) Creator/Destroyer, Site Administrator.
Specifically,
InitVars(): Add a mod_password attribute that can contain the sha
hashed list moderator's password.
ValidAdminPassword(), ConfirmAdminPassword(): Removed as obsolete.
AuthContextInfo(): Given an authorization context, and optionally a
user (if authcontext == AuthUser), return the context's secret and
cookie key. The tuple (None, None) is returned if the authcontext is
bogus. MMNotAMemberError is raised if the user isn't a member of the
list, and MMBadUserError is raised if the user's secret is None.
Authenticate(): The non-web way of doing authentication. Takes a list
of allowed authcontexts (and optionally a user name if AuthUser is one
of those contexts), and a response string (i.e. password). Returns
the authcontext from the argument sequence that matches the response,
or UnAuthorized if none of them did.
WebAuthenticate(): The web way of doing authentication. The arguments
are the same as Authenticate(), but first the cookie data is checked.
If that fails, then Authenticate() is used. Returns a flag indicating
whether authentication succeeded or not.
MakeCookie(): Now takes an authcontext and optionally a user (required
if authcontext is AuthUser). Generates a cookie item for this
context.
ZapCookie(): Now takes an authcontext and optionally a user (required
if authcontext is AuthUser). Generates an empty cookie item for this
context, effectively logging out that authcontext.
CheckCookie(): Now takes an authcontext and optionally a user (required
if authcontext is AuthUser). Returns a flag indicating whether the
authcontext's cookie matches the expected value, i.e. whether they are
cookie authenticated or not.
ChangeUserPassword(): Remove the test for IsListInitialized(), and
removed the Save() call, since all paths to this method should be
wrapped in the standard lock-modify-save-unlock fence.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
the response against the SHA encrypted password. If that fails, and
the crypt module can be imported, try that as a fallback, but if that
succeeds, update the password to be the SHA1 version.
MakeCookie(), CheckCookie(): Use Python 2.0's binascii.{un,}hexlify()
functions instead of the slower (and obsolete) ones in Utils.py.
ExtractApproval(): Removed.
|
| |
|
|
|
| |
suited in Utils than in the SecurityManager class because they don't
require the MailList object at all.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
cookies by default. Specifically,
MakeCookie(): We don't include the expires time in the mac or in the
marshaled state-tuple. These cookies live until the browser is exited
or the user explicitly logs out. In order to tell browsers this is a
session cookie, we do not set the cookie fields `Expires' or `Max-Age'
explicitly (when ADMIN_COOKIE_LIFE <= 0, as it is by default). Also,
set the RFC 2109 required `Version' field.
ZapCookie(): New method which creates a `session-logout' Set-Cookie:
header. According to RFC 2109, setting `Max-Age' to 0 ought to be
enough to zap the cookie, but for compatibility with the old Netscape
cookie spec, we also set the cookie data to the empty string.
CheckCookie(): The state-tuple and the mac no longer contain the
expired value. No need to test for now>expires and raise
MMExpiredCookieError either.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
problem. Specifically,
WebAuthenticate(): Coding style changes.
MakeCookie(): Create the cookie value in such a way as to guarantee
that only the characters [0-9][a-f] are used. This should eliminate
the need for the ugly quote-hack in CheckCookie(), and eliminate the
possibility that wacky characters like semicolon, comma, and space
(not to mention binary data) can confuse the browsers. Specifically,
we marshal the tuple ourselves and hexlify the results, setting the
key to a string. That way we avoid the Cookie module pickling the
data and creating a binary string.
Also, coerce both `issued' and `expires' to integers. Use sha
module and hexdigest() instead of md5 and digest() to hash
password+now+expires.
CheckCookie(): Remove the crufty cookie data quote-hack. Decode the
cookie value by unhexlifying and unmarshaling the string value
ourselves. Use sha module hexdigest() instead of md5's digest().
|
| | |
|
| |
|
|
|
|
| |
the mac and cookie. This breaks for some folks going through proxies,
since the client IP will change. I don't think this reduces our
security at all.
|
| |
|
|
|
| |
shorter than len(key). Just let it fail normally in those cases.
Fixes PR#158.
|
| |
|
|
| |
ExtractApproval(): Use `is' test to compare against None, not ==
|
| |
|
|
| |
MMBadUserError in that case.
|
| |
|
|
| |
web_page_url instead of the installation-global mm_cfg.DEFAULT_URL.
|
| |
|
|
|
| |
their cookie storing algorithm. This fixes PR#80, but does so with a
simpler approach than the posted patch.
|
| |
|
|
|
|
|
|
|
|
| |
can exactly specify the permissions on the file. We don't need to
save the umask since open_ex() does this. The permissions must be
exactly 0640, which restricts as much as possible. Group must be able
to read the file or site-password override in the Web interface will
not work.
Fixes PR#67
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* New method WebAuthenticate(). Takes up to three keyword arguments:
user-address, password and cookie-suffix. If password is supplied
(and authenticates OK), issue a cookie -- otherwise try to do
authentication based on cookies.
* MakeCookie(): Changed to actually return a finished Cookie object.
Takes one (non-optional) argument; the created cookie's name.
Fixed bug in setting of cookie's path.
* CheckCookie(): Now takes cookie's name as single argument, and can
raise various MMAuthenticationErrors if that cookie doesn't
authenticate OK.
admin.py: Do explicit re-authentication when changing list admin
password.
admin.py, admindb.py and private.py: Removed isAuthenticated()
function -- use MailList.WebAuthenticate() instead. This removed
the need to import Cookie, so now we don't.
|
| |
|
|
|
|
|
|
|
| |
SecurityManager: New functions MakeCookie() and CheckCookie(). These
functions work with cookies containing cookie creation and expire
time, the client's IP number, and a checksum hash of these values as
well as a secret (the lists (encrypted) admin password).
admin.py, admindb.py and private.py: isAuthenticated now uses these
new cookie functions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
address case matching. These changes require the DATA_FILE_VERSION to
be bumped, which should auto-update your config.db files. I sure hope
this works correctly! Details of changes:
MailList.GetUserSubscribedAddress(): New method. If the address is a
member, this returns the case-preserved address the user is subscribed
with. If not a member, None is returned.
MailList.GetUserCanonicalAddress(): New method. If the address is a
member, this returns the lowercased address the user is subscribed
with. If not a member, None is returned.
MailList.FindUser(): Wrote down, in a big comment, the constraints for
the dictionaries self.members, self.digest_members, self.passwords.
This wasn't always followed, but now it should be. FindUser() is now
also guaranteed to return the lowercased version of the subscribed
email address. This wasn't always the case. FindUser() also provides
a shortcut for the common case.
ApprovedAddMember(): Guarantee that passwords stored in self.passwords
are keyed off the lowercased address.
Deliverer.MailUserPassword(): Find the user's password using the
lowercased version of their address. However, be sure to use their
case-preserved address for the recipient of the password email.
Digester.SetUserDigest(): Fixed a fairly old bug where a user
switching from regular to digest membership (or vice versa) would get
their case-preserved address blown away. I don't think there's any
way to recover this information, but at least now we properly save it.
SecurityManager.ConfirmUserPassword(): Simplified address matching
stuff, since we now guarantee that FindUser() will return a lowercased
address, and that the passwords dictionary has lowercased keys.
FindUser() will return None if the address isn't found, and it also
has a built-in shortcut so that the more expensive
FindMatchingAddresses() isn't called in the common case. I eliminated
the case-insensitive password comparision that Ken rightly questioned
in his comment.
admin.py: In the list of members, display a member's case-preserved
address instead of their lowercased address. Also, obscure the URL in
the hyperlink (probably not terribly necessary).
handle_opts.py: When the password can't be found (when emailing it),
put the address we tried to find in the result message. Makes for
better debugging.
options.py: Use a better mechanism for finding if the member has a
case-preserved address different from their lowercased address.
|
| |
|
|
|
|
|
|
|
|
|
| |
Digester.SetUserDigest(), and possibly other places) the members dict
values to 1 now, as well as 0, breaking the user password recognition.
This is fucked up. Anyway, i'm dealing with that by not checking the
for a 0 from the get, but rather assuming a string returned means that
the returned value should be used instead of the index. The
complications with the different values should be fixed, as well, but
i no longer know what the right thing is, because i don't know the
purpose of the use of 1 instead of 0, if any. Sigh.
|
| |
|
|
|
|
|
|
|
|
|
| |
name optimizations - provisions to fix it are gross. It would be nice
to have an abstraction for getting the user account name under which
their password is registered (which i would call the normalized
account name). I suspect that FindUser() could serve for that, but
i'm not certain what the optimizations considerations are. I am afraid
that it is significantly more confusing, overall, to figure out which
subscription name to use (user-specified case-preserved, or lower
case) in what situation.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
dicts instead of lists, which optimizes Utils.FindMatchingAddresses
and general membership management, especially for large lists.
MailList.py now supplies .GetMembers() and .GetDigestMembers() to
supply the data in list form to anything that needs it that way.
An new install showed this worked fine with some cursory testing of
the cgi's and interactive poking around.
A detailed listing of the changes follows:
Mailman/Defaults.py.in: change data version to 11
Mailman/Digester.py: initvars now instantiates digest_members as {}
instead of []
lines 113-114 and 121-122 now use del
This change implements storing list members and digest members as
dicts instead of lists, which optimizes Utils.FindMatchingAddresses
and general membership management, especially for large lists.
MailList.py now supplies .GetMembers() and .GetDigestMembers() to
supply the data in list form to anything that needs it that way.
Though INSTALL shows up on the changed files section, a diff a few
seconds ago didn't show any differences in that file, so I hope nobody
changed it in the interim.
An new install showed this worked fine with some cursory testing of
the cgi's and interactive poking around.
A detailed listing of the changes follows:
Mailman/Defaults.py.in: change data version to 11
Mailman/Digester.py: initvars now instantiates digest_members as {}
instead of []
lines 113-114 and 121-122 now use del
list.[digest_]member instead of
list.[digest_]members.remove
when figuring who to actually send digests to,
use list.GetDigestMembers() instead of
list.digest_members.
Mailman/HTMLFormatter: now uses list.Get[Digest]Members to get
subscribers, and length of digested subscribers
and regular members
MailCommandHandler, SecurityManager,Cgi/handle_opts, Cgi/options: all
simple replacements of list.[digest_]members with
list.Get[Digest]Members().
Mailman/Cgi/admin.py: mostly simple replacements of
list.[digest_]members with the Get..() methods, however, the
membership management section now works much quicker and changes
digest->nodigest subscriptions via dictionary manipulations.
Mailman/versions.py: updates lists to use dicts and changed
list.[digest_]members to use the list.Get[Digest]Members() methods.
Mailman/Utils.py: added a function "GetPossibleMatchingAddresses"
which when fed an address, returns the list of addresses that "smart"
address matching would match.
changed FindMatchingAddresses(name, list) to use a new signature:
FindMatchingAddresses(name, *dicts), where dicts is a list of
dictionaries keyed by addresses. Just realized that this would better
be FindMatchingAddresses(name, dict, *dicts) so that it enforces
atleast 2 args... I'll make that change in a sec.
All uses of FindMatchingAddresses have been changed to fit the new
arguments.
scott
----:**-F1 cvs30458aaa 1:12PM 0.98 Mail (Text Fill)--L59--32%-------------------------------------------
?
|
| | |
|
| |
|
|
|
|
| |
1) the password data file was changed to g-w (which is good)
2) the open(...) used "r+" instead of "r" (which is bad)
I changed #2...
|
| |
|
|
|
|
|
| |
interface to an md5 digest if the import fails. This way, we don't
have to tell people to recompile python if they compiled it out of the
box. (since crypt is no longer in by default).
mm_security now uses mm_crypt instead of crypt.
|
| | |
|
| |
|
|
|
| |
different variable from mm_cfg. The file location is stored in
SITE_PW_FILE.
|
| | |
|
| |
|
|
|
|
|
| |
do so.
Added a copy of the GNU GPL.
Added information about mailman-users in README, and reworded some text in there (made the credits less verbose... perhaps they should move to a credits file?)
|
| | |
|
| |
|
|
| |
__version__ info.
|