summaryrefslogtreecommitdiff
path: root/Mailman/SecurityManager.py
Commit message (Collapse)AuthorAgeFilesLines
* Bite the bullet: rename the Mailman package to mailman.Barry Warsaw2008-02-271-306/+0
|
* Tweak copyright years.Barry Warsaw2008-02-071-1/+1
|
* It all started by trying to remove MailList.Create() and use the IListManagerBarry Warsaw2007-08-051-7/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | interface to create and delete lists. Mostly that's working now, but I need unit tests for most of the new work contained in this revision. Implemented a rudimentary 'list styles' subsystem, along with interfaces, but no tests yet. Moved all of MailList.InitVars() into a DefaultStyle, which is always available at priority zero. It's used by default if there are no matching styles for a mailing list. Because of the list styles, we can now get rid of (almost) all InitVars() methods. And because of /that/ we can get rid of the mixin clases whose sole purpose was to provide an InitVars() method. Yay for code removal! Mixin modules/classes removed: Autoresponder, GatewayManager, TopicManager. Removed the Mailman/ext crufty extension mechanism. Extensions will now be done using setuptools plugins. Hopefully this will take us everywhere we need to go, but I'll add Mailman.ext back if necessary later. Mailiman.app.create module added to implement a common, higher-level list creation feature. This is used by bin/newlist now, though some of that functionality (namely, ensuring the owners exist in the database, and notifying the owners) should be moved here. The MTA plugins aren't yet integrated into this, but need to be. Mailman.app.plugins module added to generalize setuptools plugin management. Defaults.DEFAULT_REPLY_GOES_TO_LIST now gets initialized with a proper enum. Also, the duplicate DeliveryMode and DeliveryStatus enums are removed from Defaults because they're in Mailman.constants. Added Errors.DuplicateStyleError. Updated Utils.list_exists() to use the new IListManager.get() interface, which has been changed to return None if the list doesn't exist (for consistency) instead of raising an exception. Utils.list_names() also needed to be fixed to use config.db.list_manager. bin/make_instance, bin/newlist, bin/rmlist changed to use parser.error() istead of printing to sys.stderr and sys.exit(1). bin/newlist and bin/rmlist now works with the IListManager interface, so you can create and delete lists from the command line again. The CLI for newlist has been much simplified; it no longer prompts for missing positional arguments. It now uses a more traditional CLI. newlist also accepts zero to many owners, and it ensures that the owners are all in the database. It no longer asks for a list password, because this doesn't make sense any more. bin/withlist has also been fixed to work with the IListManager interface. There are lots of XXXs and FIXMEs that need to be resolved before this can land. Also, we need to test all this stuff before it can land. Configuration.load() is now taught to search in sys.argv[0] for var/etc/mailman.cfg since this is where it is for egg development layouts. Also, VAR_DIR must be abspath'd. Added an __all__ to Mailman.constants, and added an Action enum. The listmanager implementation has to set the mlist.created_at time. There's also a bit of crufty refactoring going on to instantiate the roster objects whenever the list is created or retrieved from the database. Several MailingList column types are now set to our custom TimeDeltaType, which knows how to store a datetime.timedelta. A SQLAlchemny converter type is added to Mailman.database.types. I also fixed a bug in the EnumType implementation.
* Passwords done right.bwarsaw2007-01-141-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | First off, there are several password hashing schemes added including SHA, salted-SHA, and RFC 2989 PBKDF2 (contributed by Bob Fleck). Then we encode the password using RFC 2307 style syntax. At least I think: specifically things like the PRF and iteration count for PBKDF2 are encoded the way I /think/ is intended for RFC 2307 but I could be wrong. Seems darn hard to find definitive information about that. In any event, even though CLEARTEXT passwords are supported, they are mostly deprecated, even for user passwords. It also allows us to easily update all passwords to a new hashing scheme when the existing schemes get cracked. The default scheme (specified in Defaults.py.in) is salted-SHA with a 20 byte salt (the salt length and PBKDF2 iteration counts can only be specified in the passwords.py file). These hashed passwords are used for user passwords, list owner and moderator passwords, and site and list creator passwords. Of course this means that user password reminders are impossible now. They've been ripped out of the code for a while, but now we'll need to implement password resets since user passwords cannot be recovered. bin/export has had several changes: - export no longer converts to dollar strings. Were assuming dollar strings are used by default for all new lists and any imported lists will already be converted to dollar strings. - Likewise, rip out the password scheme stuff, since cleartext passwords can never be exported, so we might as well always include the member's hashed password. - Fix exporting to stdout when that stream can only handle ascii by wrapping stdout in a utf-8 codec writer. Other changes: - add a missing import to HTTPRunner.py - Convert GUIBase.py to use Defaults.* for constants instead of mm_cfg.* - Remove pre-Python 2.4 compatibility from Utils.py. We've already said Python 2.4 will be a minimum requirement. - Change the permissions on the global password file. The default 007 umask is used and should be good enough. - bin/newlist adds the ability to specify the password scheme (or list the available schemes) for the list owner password. It is not possible to set the scheme on a per-list basis. bin/mmsitepass does the same, but for the site and list creator passwords. - Fix a nasty problem with bin/import. The comment in the code says it best: # XXX Here's what sucks. Some properties need to have # _setValue() called on the gui component, because those # methods do some pre-processing on the values before they're # applied to the MailList instance. But we don't have a good # way to find a category and sub-category that a particular # property belongs to. Plus this will probably change. So # for now, we'll just hard code the extra post-processing # here. The good news is that not all _setValue() munging # needs to be done -- for example, we've already converted # everything to dollar strings. - Set the 'debug' logger to logging.DEBUG level. It doesn't seem to make much sense for the debugging log to ignore debug messages.
* Merged revisions 8113-8121 via svnmerge from bwarsaw2006-12-291-52/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | https://mailman.svn.sourceforge.net/svnroot/mailman/branches/tmp-sqlalchemy-branch ................ r8114 | bwarsaw | 2006-12-06 00:16:54 -0500 (Wed, 06 Dec 2006) | 44 lines Initial take on using SQLAlchemy to store list data in lieu of Python pickles. While all the list data (including OldStyleMemberships attributes) are stored in the database, many attributes are stored as PickleTypes binary data. This isn't idea but it gets things working until a more sophisticated schema can be developed. MailList class is now a new-style class, as is required by SQLAlchemy. This makes several things, er, interesting. Rip out all the low-level pickle reading and writing stuff. Hook SA transaction events into Lock() and Unlock(). Move the hooking of the _memberadaptor into InitTempVars(), which gets called by the SQLAlchemy hooks (MailList.__init__() never is). Add an initialize.py module which centralizes all the initialization bits that command line scripts have to do, including configuration, logging, and atabase initialization. This change also converts bin/withlist to mmshell wrapper. Update to SQLAlchemy 0.3.1. Revamp paths.py.in considerably. There were several problems with the old way. We no longer disable default loading of site-packages so we don't need to add Python's site-packages back to sys.path. Also, because site.addsitedir() causes things like .pth paths to be /appended/ to sys.path, they actually won't override any site-installed packages. E.g. if SQLAlchemy is installed in the system Python, our version will not override. IIUC, setuptools-based packages can be configured to work properly in the face of package versions, however not all packages we currently depend on are setuptools-based. So instead, we steal a bit of stuff from site.py but change things so the prepend .pth stuff to sys.path. Update several modules to use True/False and whitespace normalization. Convert from mm_cfg to config object. Modernize a few coding constructs. Add a couple of exceptions to handle database problems. In the export script, include the widget type in the elements. This helped in my stupid little throw away conversion script, but I think it will be more generally useful. Add an interact.py module which refactors interactive interpreter access. Mostly this is used by withlist -i, but it lets us import Mailman.interact and drop into a prompt just about anywhere (e.g. debugging). ................ r8115 | bwarsaw | 2006-12-07 09:13:56 -0500 (Thu, 07 Dec 2006) | 22 lines Start to flesh out more of the SQLAlchemy mechanisms. Added a MailList.__new__() which hooks instantiation to use a query on dbcontext to get an existing mailing list. A 'no-args' call means we're doing a Create(), though eventually that will change too. For now, disable the CheckVersion() call. Eventually this will be folded into schema migration. list_exists(): Rewrite to use the dbcontext query to determine if the named mailing list exists or not. Requires the fqdn_listname. Eradicate two failed member adaptors: BDBMemberAdaptor and SAMemberships. Change the way the DBContext holds onto tables. It now keeps a dictionary mapping the table's name to the SA Table instance. This makes it easier to look up and use the individual tables. Add 'web_page_url' as an attribute managed by SA, and remove a debugging print. ................ r8116 | bwarsaw | 2006-12-11 07:27:47 -0500 (Mon, 11 Dec 2006) | 29 lines Rework the whole dbcontext and transaction framework. SA already handles nested transactions so we don't have to worry about them. However, we do have the weird situation where some transactions are tied to MailList .Lock()/.Unlock()/.Save() and some are tied to non-mlist actions. So now we use an @txn decorator to put methods in a session transaction, but then we also hook into the above MailList methods as possibly sub-transactions. We use a weakref subclass to manage the MailList interface, with a dictionary mapping MailList fqdn_listnames against transactions. The weakrefs come in by giving us a callback when a MailList gets derefed such that we're guaranteed to rollback any outstanding transaction. Also, we have one global DBContext instance but rather than force the rest of Mailman to deal with context objects, instead we expose API methods on that object into the Mailman.database module, which the rest of the code will use. Such methods must be prepended with 'api_' to get exposed this way. bin/rmlist now works with the SA-backend. I refactored the code here so that other code (namely, the test suite) can more easily and consistently remove a mailing list. This isn't the best place for it ultimately, but it's good enough for now. New convenience functions Utils.split_listname(), .fqdn_listname(). Convert testall to use Mailman.initialize.initialize(). Not all tests work, but I'm down to only 8 failures and 7 errors. Also, do a better job of recovering from failures in setUp(). MailList.__new__() now takes keyword arguments. ................ r8117 | bwarsaw | 2006-12-11 22:58:06 -0500 (Mon, 11 Dec 2006) | 7 lines Unit test repairs; even though the unit tests are still pretty fragile, everything now passes with the SQLAlchemy storage of list data. Added missing 'personalize' column. Converted mailmanctl and qrunner to initialize() interface. Fixed _cookie_path() to not fail if SCRIPT_NAME is not in the environment. ................ r8118 | bwarsaw | 2006-12-27 18:45:41 -0500 (Wed, 27 Dec 2006) | 21 lines Utils.list_names(): Use a database query to get all the list names. dbcontext.py: Added api_get_list_names() to support Utils.list_names(). listdata.py: Added two additional MailList attributes which need to be stored in the database. The first is 'admin_member_chunksize' which isn't modifiable from the web. The second is 'password' which holds the list's password. HTMLFormatObject: item strings can now be unicodes. bin/list_lists.py: Must call initialize() to get the database properly initialized, not just config.load(). This will be a common theme. SecurityManager.py: - Remove md5 and crypt support - Added mailman.debug logger, though it will be only used during debugging. - The 'secret' can be a unicode now. - A few coding style updates; repr() instead of backticks, 'key in dict' instead of 'dict.has_key(key)' ................ r8119 | bwarsaw | 2006-12-27 19:13:09 -0500 (Wed, 27 Dec 2006) | 2 lines genaliases.py: config.load() -> initialize() ................ r8120 | bwarsaw | 2006-12-27 19:17:26 -0500 (Wed, 27 Dec 2006) | 9 lines Blocked revisions 8113 via svnmerge ........ r8113 | bwarsaw | 2006-12-05 23:54:30 -0500 (Tue, 05 Dec 2006) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-8112" from https://mailman.svn.sourceforge.net/svnroot/mailman/branches/tmp-sqlalchemy-branch ........ ................ r8121 | bwarsaw | 2006-12-28 23:34:52 -0500 (Thu, 28 Dec 2006) | 20 lines Remove SIGTERM handling from all the CGI scripts. This messes with HTTPRunner because when you issue "mailmanctl stop" after the signal handler has been installed, the process will get a SIGTERM, the signal handler will run, and the process will exit with a normal zero code. This will cause mailmanctl to try to restart the HTTPRunner. I don't think we need that stuff at all when running under wsgi with a SQLAlchemy backend. If mailmanctl kills the HTTPRunner in the middle of the process, I believe (but have not tested) that the transaction should get properly rolled back at process exit. We need to make sure about this, and also we need to test the signal handling functionality under traditional CGI environment (if we even still want to support that). Also, make sure that we don't try to initialize the loggers twice in qrunner. This was the cause of all the double entries in logs/qrunner. Fix a coding style nit in mailmanctl.py. De-DOS-ify line endings in loginit.py. ................
* Postfix LMTP related brushups.tkikuchi2006-11-261-20/+1
| | | | | | | | | | | | | | - Configurable no-list error. - Ultimate loop stop address in transport -> aliases. - LMTP_ONLY_DOMAIN needs no individual transport entry. - Use of alias/lmtp is exclusive. WSGI brushups. - _cookie_path() was made simple and retain common cookie for admin/admindb/... etc. - Removed absolute=1 from admindb/confirm/create/options. configuration.py - Use of add_runner() in etc/mailman.cfg needs change. config is not loaded yet?
* Fix environ['SCRIPT_NAME'] to match CGI spec.tkikuchi2006-11-131-3/+3
| | | | | | | | Also, the now scripts can be accessed by arbitrary script base. E.g. /listinfo can be accessed by /mailman/listinfo or /mailman/blah/listinfo etc. etc. This is useful in testing wsgi directly without apache frontend but we may have to limit the length or depth of prefixed script base.
* Repair a problem with cookie paths reported by Tokio when HTTPRunner is usedbwarsaw2006-10-301-16/+38
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | but a reverse proxy maps our wsgiref server into an upstream server's web space. Here's the basic problem: the Set-Cookie header we return has a Path attribute which must match subsequent request uri's in order for the client to send the cookie data back to us later in a Cookie header of that subsequent request. The problem though is that we cannot guarantee that we know how our wsgi server is mapped into the upstream proxy. It's probably '/mailman/' for backward compatibility, but there's no way for us to tell, because there's nothing specifically included in the request that tells us what the originally requested uri is. If we get the cookie path wrong, the effect is to require a login every time an admin page is hit, because the client will not see a matching path prefix and will not send us the cookie data. We solve this (albeit, by hack) by looking at the HTTP_REFERER environment variable we see. This will point to the admin login page on which the admin password was entered. We'll pick this uri apart to attempt to find the prefix at which our wsgi server was mapped. If we find this, we'll use it to craft an appropriate cookie path. Hopefully. If that cgi environment variable is not available, we just return the path as we've seen it. This approach allows for accessing the admin pages either through a reverse proxy or directly, with no additional configuration necessary. In fact, both access mechanisms can work at the same time; try hitting these two uri's with different browsers: http://example.com/mailman/admin/mylist@example.com/general http://example.com:2580/admin/mylist@example.com/general The first will hit our reverse proxy, and the second will hit our wsgi server directly. The responses will included two different cookie paths, but both will work! This is an important principle to uphold, especially for debugging purposes. Note that I could have added a configuration variable to handle the cookie path remapping, but then we'd have to support either the reverse proxy or the wsgi server, but not (easily) both. Plus, it's another configuration variable. Yuck. Note that Apache 2.2 has something called the ProxyPassReverseCookiePath directive, which should probably be used if available. It's not in Apache 2.0, which is probably the most prevalent server in use with Mailman right now, so we can't count on it. Plus, if ProxyPassReverseCookiePath is available, our algorithm should still work. What about other proxy servers? Dunno. We'll have to wait for feedback from users. This change also fixes a buglet with MTA/Postfix.py when POSTFIX_STYLE_VIRTUAL_DOMAINS is used. You can end up trying to call _update_maps() before data/aliases exist. This just defers that call until it's guaranteed both the transport and the alias files have been created. Also, finish converting SecurityManager.py to use the configuration object (and the Defaults module where appropriate) instead of mm_cfg.py.
* More work on the WSGI support. So far, I've tested most of the admin.py linksbwarsaw2006-10-151-10/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | and some of the admindb.py links. There may still be breakage in other parts of the interface and I haven't gone back to verify that traditional CGI still works. Changes: - Add wsgiref-0.1.2-py2.4.egg so that we can still do WSGI in Python 2.4, which doesn't come with wsgiref. Of course this means we /also/ have to add setuptools-0.5c3 because eggs require setuptools. - Style cleanups in HTTPRunner.py and wsgi_app.py. Also, use cStringIO instead of StringIO. - All internal links within the listinfo and admin pages are (or at least should be ;) relative now. This should make other things better, such as running Mailman over https or alternative ports. It does kind of mean that web_page_url is obsolete, but I haven't looked at whether we can completely eradicate it. - ValidateEmail(): Use ' ' in s instead of s.count(' ') > 0. - GetPathPieces(): When path is false, return the empty list instead of None, so we can still len() it. - ScriptURL(): Much simpler. To support relative urls as the default, we change the API so that it only takes a 'target' argument (i.e. the script we want to link to). It no longer takes 'absolute' or 'web_page_url', and it constructs its link from GetPathPieces(), the target, and the cgi extension. - GetRequestURI(): code style updates. - Mailman/bin/show_config.py: De-DOS-line-ending-ification. - export.py: A few modifications, although this is likely still not final (I'm still working on the import script). First, for <option> elements, don't put the value in an attribute, put it in the text body of the element. Second, put the list <option> tags in a <configuration> element. Third, put the preferred language on an <option> tag with a 'preferred_language' name attribute value. - SecurityManager: Make sure that MakeCookie() and ZapCookie() use the same 'path' cookie value by refactoring that into a separate method. That method now returns just the SCRIPT_NAME and the full listname. web_page_url doesn't enter into it. - loginit.py: Add a 'debug' logger since it's just too useful to have :) - admin.py: Remove the extra / right before the query string in ?VARHELP urls. That extra / turns out to be problematic with the relative url scheme we're using now. - Auth.py: whitespace normalization and copyright years update. Also, remove a couple of unnecessary imports. Also, make sure that the actionurl is relative. - create.py: Typo. - private.py: mm_cfg -> config object - In MailList.py: GetScriptURL() can be written in terms of Utils.ScriptURL() now.
* Upgrade to email package version 4.0.1. Because email 4.0.1 is onlybwarsaw2006-07-301-7/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | compatible back to Python 2.3, this change should not get back ported to Mailman 2.1. Port to Python 2.5. The non-test suite changes should get back ported to Mailman 2.1 (which I will do next), but don't worry about the test suite ones because MM2.1's test suite is hopeless. Specifically: - In SecurityManager.py, fix the parsecookie() code to work with Python 2.5 generated cookie text. The latter was changed to be more RFC compliant so it does not output training semicolons for each line of cookie text. This broke the splitting rules, so now first split on newlines, then on ';\s*'. This should work across all Python versions. - In Python 2.5, exceptions are new-style, and thus are no longer of ClassType. The instantiation type test in hold_for_approval() was too naive. - Raising strings generates deprecation warnings in Python 2.5. Switch the one weird use of this in Utils.py to use a class exception. Don't call it "quick exit" though because it's probably not. - In the tests, use True/False instead of 1/0 - Use failUnless/failIf instead of assertEqual against True/False. - In the tests, use Message.get_content_type() instead of Message.get_type() since the latter is gone in email 4.0.1. Same with get_content_maintype() and get_main_type().
* Remove most uses of the types module, in favor of isinstance checks againstbwarsaw2006-04-171-3/+2
| | | | | | the builtin types. Two still remain: a check against ClassType and a check against MethodType. Also, fix some hinky type comparisons to use isinstance() consistently.
* - Convert all logging to Python's standard logging module. Get rid of allbwarsaw2006-04-171-6/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | traces of our crufty old Syslog. Most of this work was purely mechanical, except for: 1) Initializing the loggers. For this, there's a new module Mailman/loginit.py (yes all modules from now on will use PEP 8 names). We can't call this 'logging.py' because that will interfere with importing the stdlib module of the same name (can you say Python 2.5 and absolute imports?). If you want to write log messages both to the log file and to stderr, pass True to loginit.initialize(). This will turn on propagation of log messages to the parent 'mailman' logger, which is set up to print to stderr. This is how bin/qrunner works when not running as a subprocess of mailmanctl. 2) The driver script. I had to untwist the StampedLogger stuff and implement differently printing exceptions and such to log/error because standard logging objects don't have a write() method. So we write to a cStringIO and then pass that to the logger. 3) SMTPDirect.py because of the configurability of the log messages. This required changing SafeDict into a dict subclass (which is better than using UserDicts anyway -- yay Python 2.3!). It's probably still possible to flummox things up if you change the name of the loggers in the SMTP_LOG_* variables in mm_cfg.py. However, the worst you can do is cause output to go to stderr and not go to a log file. Note too that all entry points into the Mailman system must call Mailman.loginit.initialize() or the log output will go to stderr (which may occasionally be what you want). Currently all CGIs and qrunners should be working properly. I wish I could have tested all code paths that touch the logger, but that's infeasible. I have tested this, but it's possible that there were some mistakes in the translation. - Mailman.Bouncers.BounceAPI.Stop is a singleton, but not a class instance any more. - True/False code cleanup, PEP 8 import restructuring, whitespace normalization, and copyright year updates, as appropriate.
* Now that Python 2.3 is the minimum requirement for Mailman 2.2:bwarsaw2006-04-151-14/+9
| | | | | | | | | | | - Remove True/False binding cruft - Remove __future__ statements for nested scopes - Remove ascii_letters import hack from Utils.py - Remove mimetypes.guess_all_extensions import hack from Scrubber.py - In Pending.py, set _missing to object() (better than using []) Also, update copyright years where appropriate, and re-order imports more to my PEP 8 tastes. Whitespace normalize.
* back porting from 2.1.6tkikuchi2005-08-281-38/+48
|
* FSF office has moved. chdcking in for MAIN branch.tkikuchi2005-08-271-1/+1
|
* parsecookie(): Be defensive about bogus cookie data.bwarsaw2003-02-041-2/+6
|
* CheckCookie(), __checkone(), parsecookie(): A fix for the MM2.0/MM2.1bwarsaw2003-01-311-12/+22
| | | | | | | | 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.
* Updated comments to reflect that NotAMemberError is the one truebwarsaw2002-12-021-3/+3
| | | | exception that can get raised.
* Authenticate(): Checking in a change discussed a while ago onbwarsaw2002-08-291-8/+6
| | | | | | | | 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.
* Authenticate(): SF bug # 585776 complains that crypt.crypt() can raisebwarsaw2002-07-241-2/+14
| | | | | | | | | 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.
* CheckCookie(): If the SimpleCookie constructor throws a CookieError,bwarsaw2002-01-291-1/+4
| | | | catch it and return false.
* "import Cookie" instead of "from Cookie import SimpleCookie as Cookie"bwarsaw2002-01-111-12/+9
| | | | | | | | | | | | | 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.
* AuthContextInfo(): If ALLOW_SITE_ADMIN_COOKIES is true, and there is abwarsaw2002-01-061-7/+12
| | | | | site password, and we're doing AuthSiteAdmin, then issue a secret/key combination that allows the site password to be cookie-fied.
* CheckCookie(): Let's be explicit about using the Cookie.SimpleCookiebwarsaw2001-11-201-6/+19
| | | | | | | | | | | 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.
* AuthContextInfo(): Python 2.x's Cookie.py module is strict about legalbwarsaw2001-10-091-6/+7
| | | | | | | | | | | | | | | | | | 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.
* AuthContextInfo(): Python's standard Cookie.py doesn't allow colons inbwarsaw2001-10-041-2/+2
| | | | | | | | 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.
* Use Python's default Cookie.py module instead of our own copy.bwarsaw2001-10-011-1/+1
|
* MakeCookie(): If the secret isn't a string, raise MMBadUserError.bwarsaw2001-08-161-2/+2
| | | | | __checkone(): Likewise, if the secret isn't a string, return 0 (i.e. no the user isn't authenticated).
* InitVars(): With the new mixin architecture, InitVars() needs to takebwarsaw2001-07-191-19/+7
| | | | | | | | | | | | | 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.
* SecurityManager.MakeCookie(): 'MMBadUserError' -> 'Errors.MMBadUserError'twouters2001-07-101-1/+1
|
* ConfirmUserPassword(): Obsolete; removed.bwarsaw2001-07-031-27/+49
| | | | | | | | | | | | | 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.
* CheckCookie(): If the authcontext is AuthUser and the `user' argumentbwarsaw2001-06-011-1/+27
| | | | | | | | | | | | | 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.
* Authenticate(): When sha hex digesting the response, save the resultsbwarsaw2001-05-311-2/+4
| | | | | in a temporary variable and check that variable against the secret (this is so that subsequent checks have the raw password).
* Changes to support the new world order of authentication, usingbwarsaw2001-05-311-61/+150
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* WebAuthenticate(): Minor simplification.bwarsaw2001-05-161-3/+3
|
* ValidAdminPassword(): CheckSiteAdminPassword -> check_global_passwordbwarsaw2001-05-091-2/+2
|
* ValidAdminPassword(): First, use SHA1 as the default hash, and comparebwarsaw2001-02-151-18/+25
| | | | | | | | | | | 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.
* SetSiteAdminPassword(), CheckSiteAdminPassword(): These are betterbwarsaw2000-10-021-20/+2
| | | | | suited in Utils than in the SecurityManager class because they don't require the MailList object at all.
* ZapCookie(): add a comment about why expires=0 isn't set here.bwarsaw2000-07-211-0/+1
|
* Several changes to the cookie management code, to support sessionbwarsaw2000-07-201-13/+29
| | | | | | | | | | | | | | | | | | | | 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.
* Several changes which will hopefully fix the cookie re-authenticationbwarsaw2000-07-191-37/+33
| | | | | | | | | | | | | | | | | | | | | | | 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().
* Update the copyright lines to include the years 1999 & 2000.bwarsaw2000-03-211-1/+1
|
* MakeCookie(), CheckCookie(): Don't include the client's IP address inbwarsaw1999-12-091-19/+17
| | | | | | 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.
* CheckCookie(): Watch out for cookiedata getting truncated to bebwarsaw1999-11-261-4/+6
| | | | | shorter than len(key). Just let it fail normally in those cases. Fixes PR#158.
* Remove some extraneous parens.bwarsaw1999-09-041-11/+9
| | | | ExtractApproval(): Use `is' test to compare against None, not ==
* ConfirmUserPassword(): It's possible that user is None. Raise abwarsaw1999-07-221-0/+2
| | | | MMBadUserError in that case.
* MakeCookie(): Set cookie's "path" based on the list-specific settinghmeland1999-07-221-1/+1
| | | | web_page_url instead of the installation-global mm_cfg.DEFAULT_URL.
* CheckCookie(): Workaround for IE4.01 (and other pre-5.0 MSIEs?) bug inbwarsaw1999-07-161-2/+17
| | | | | their cookie storing algorithm. This fixes PR#80, but does so with a simpler approach than the posted patch.
* SetSiteAdminPassword(): Open data/adm.pw with Utils.open_ex() so webwarsaw1999-07-091-5/+3
| | | | | | | | | | 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
* SecurityManager:hmeland1999-06-131-11/+43
| | | | | | | | | | | | | | | | | | * 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.