aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman
diff options
context:
space:
mode:
authorbwarsaw <>2004-12-30 20:49:31 +0000
committerbwarsaw <>2004-12-30 20:49:31 +0000
commit292e9a631ebec94138bd4f3b1f5a1a9faea9cb38 (patch)
tree1a48bcb9e9fbcce81a636e0af2f97ee57cf7f82c /Mailman
parentbef8ca35019a13a4973086e7bf60d52e815763da (diff)
downloadmailman2-292e9a631ebec94138bd4f3b1f5a1a9faea9cb38.tar.gz
mailman2-292e9a631ebec94138bd4f3b1f5a1a9faea9cb38.tar.xz
mailman2-292e9a631ebec94138bd4f3b1f5a1a9faea9cb38.zip
From the NEWS file:
- Added the ability for Mailman generated passwords (both member and list admin) to be more cryptographically secure. See new configuration variables USER_FRIENDLY_PASSWORDS, MEMBER_PASSWORD_LENGTH, and ADMIN_PASSWORD_LENGTH. Also added a new bin/withlist script called reset_pw which can be used to reset all member passwords. Passwords generated by Mailman are now 8 characters by default for members, and 10 characters for list administrators.
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Cgi/create.py3
-rw-r--r--Mailman/Defaults.py.in15
-rw-r--r--Mailman/Utils.py51
3 files changed, 62 insertions, 7 deletions
diff --git a/Mailman/Cgi/create.py b/Mailman/Cgi/create.py
index 09e4790c..a67614cf 100644
--- a/Mailman/Cgi/create.py
+++ b/Mailman/Cgi/create.py
@@ -125,7 +125,8 @@ def process_request(doc, cgidata):
blank if you want Mailman to autogenerate the list
passwords.'''))
return
- password = confirm = Utils.MakeRandomPassword(length=8)
+ password = confirm = Utils.MakeRandomPassword(
+ mm_cfg.ADMIN_PASSWORD_LENGTH)
else:
if password <> confirm:
request_creation(doc, cgidata,
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in
index 3c7ecfdb..ca1fcd65 100644
--- a/Mailman/Defaults.py.in
+++ b/Mailman/Defaults.py.in
@@ -787,6 +787,21 @@ ADMIN_CATEGORIES = [
# list's config variable default_member_moderation.
DEFAULT_NEW_MEMBER_OPTIONS = 256
+# Specify the type of passwords to use, when Mailman generates the passwords
+# itself, as would be the case for membership requests where the user did not
+# fill in a password, or during list creation, when auto-generation of admin
+# passwords was selected.
+#
+# Set this value to Yes for classic Mailman user-friendly(er) passwords.
+# These generate semi-pronounceable passwords which are easier to remember.
+# Set this value to No to use more cryptographically secure, but harder to
+# remember, passwords -- if your operating system and Python version support
+# the necessary feature (specifically that /dev/urandom be available).
+USER_FRIENDLY_PASSWORDS = Yes
+# This value specifies the default lengths of member and list admin passwords
+MEMBER_PASSWORD_LENGTH = 8
+ADMIN_PASSWORD_LENGTH = 10
+
#####
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index 03575998..a6e07e10 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2004 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -27,12 +27,13 @@ from __future__ import nested_scopes
import os
import re
-import random
-import urlparse
+import cgi
import sha
-import errno
import time
-import cgi
+import errno
+import base64
+import random
+import urlparse
import htmlentitydefs
import email.Header
import email.Iterators
@@ -298,12 +299,50 @@ for v in _vowels:
_syllables.append(v+c)
del c, v
-def MakeRandomPassword(length=6):
+def UserFriendly_MakeRandomPassword(length):
syls = []
while len(syls) * 2 < length:
syls.append(random.choice(_syllables))
return EMPTYSTRING.join(syls)[:length]
+
+def Secure_MakeRandomPassword(length):
+ bytesread = 0
+ bytes = []
+ fd = None
+ try:
+ while bytesread < length:
+ try:
+ # Python 2.4 has this on available systems.
+ newbytes = os.urandom(length - bytesread)
+ except (AttributeError, NotImplementedError):
+ if fd is None:
+ try:
+ fd = os.open('/dev/urandom', os.O_RDONLY)
+ except OSError, e:
+ if e.errno <> errno.ENOENT:
+ raise
+ # We have no available source of cryptographically
+ # secure random characters. Log an error and fallback
+ # to the user friendly passwords.
+ return UserFriendly_MakeRandomPassword(length)
+ newbytes = os.read(fd, length - bytesread)
+ bytes.append(newbytes)
+ bytesread += len(newbytes)
+ s = base64.encodestring(EMPTYSTRING.join(bytes))
+ # base64 will expand the string by 4/3rds
+ return s.replace('\n', '')[:length]
+ finally:
+ if fd is not None:
+ os.close(fd)
+
+
+def MakeRandomPassword(length=mm_cfg.MEMBER_PASSWORD_LENGTH):
+ if mm_cfg.USER_FRIENDLY_PASSWORDS:
+ return UserFriendly_MakeRandomPassword(length)
+ return Secure_MakeRandomPassword(length)
+
+
def GetRandomSeed():
chr1 = int(random.random() * 52)
chr2 = int(random.random() * 52)