summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin W. Smith <benjaminwarfield@just-another.net>2009-10-19 11:08:44 -0400
committerBenjamin W. Smith <benjaminwarfield@just-another.net>2009-10-19 11:08:44 -0400
commit00edbd67c326a4c71c882f409c8459e5a2df13fa (patch)
treeb06b69369ef51e179ed037e32732ceea157b2b7f
parente179fec1f865ede349873a436d5eb2ed4e98da9b (diff)
downloadpyapache-00edbd67c326a4c71c882f409c8459e5a2df13fa.tar.bz2
pyapache-00edbd67c326a4c71c882f409c8459e5a2df13fa.tar.xz
pyapache-00edbd67c326a4c71c882f409c8459e5a2df13fa.zip
Pep8 cleanup, dbm module to manage a hash DB of users for an apacheHEADmaster
htdigest/htpasswd setup.
-rwxr-xr-x[-rw-r--r--]__init__.py0
-rwxr-xr-xdbm.py60
-rwxr-xr-x[-rw-r--r--]htpasswd.py6
-rwxr-xr-xmd5.py25
-rwxr-xr-x[-rw-r--r--]password.py5
5 files changed, 83 insertions, 13 deletions
diff --git a/__init__.py b/__init__.py
index e69de29..e69de29 100644..100755
--- a/__init__.py
+++ b/__init__.py
diff --git a/dbm.py b/dbm.py
new file mode 100755
index 0000000..36b6233
--- /dev/null
+++ b/dbm.py
@@ -0,0 +1,60 @@
1#!/usr/bin/env python
2"""
3Utilities to manage a hash db of users for apache
4"""
5import anydbm
6import htpasswd
7__all__ = ["add_user", "delete_user", "update_user",
8 "get_user", "list_users", "raw_add"]
9
10
11def get_user(user, db):
12 """ Get user info from the DB """
13 db_dict = anydbm.open(db, 'r')
14 ret_user = "%s:%s" %(user, db_dict[user])
15 db_dict.close()
16 return ret_user
17
18
19def list_users(db):
20 """ List all the users in the DB """
21 db_dict = anydbm.open(db, 'r')
22 ret_str = '\n'.join(["%s:%s" %(k, v) for k, v in db_dict.iteritems()])
23 db_dict.close()
24 return ret_str
25
26
27def add_user(user, passwd, db):
28 """ Add user to the DB, creating if need be """
29 db_dict = anydbm.open(db, 'c')
30 db_dict[user] = htpasswd.hash_password(passwd)
31 db_dict.close()
32 return True
33
34
35def raw_add(line, db):
36 """ Add raw line to the DB """
37 db_dict = anydbm.open(db, 'w')
38 user, passwd = line.split(':')
39 db_dict[user] = passwd
40 db_dict.close()
41 return True
42
43
44def delete_user(user, db):
45 """ Remove user from the DB """
46 db_dict = anydbm.open(db, 'w')
47 del db_dict[user]
48 db_dict.close()
49 return True
50
51
52def update_user(user, passwd, db):
53 """ Change the users pass in the DB """
54 db_dict = anydbm.open(db, 'w')
55 if user in db_dict:
56 db_dict[user] = htpasswd.hash_password(passwd)
57 db_dict.close()
58 return True
59 else:
60 return False
diff --git a/htpasswd.py b/htpasswd.py
index 3641c34..0b79445 100644..100755
--- a/htpasswd.py
+++ b/htpasswd.py
@@ -8,7 +8,8 @@ Released under the terms of the BSD license.
8A collection of classes and functions to manipulate apache htaccess files. 8A collection of classes and functions to manipulate apache htaccess files.
9""" 9"""
10 10
11__all__ = [ "generate_user" ] 11__all__ = ["generate_user"]
12
12 13
13def hash_password(passwd, ctype="crypt"): 14def hash_password(passwd, ctype="crypt"):
14 """Create an Apache-style password hash. 15 """Create an Apache-style password hash.
@@ -25,10 +26,11 @@ def hash_password(passwd, ctype="crypt"):
25 elif ctype is "md5": 26 elif ctype is "md5":
26 from apachelib.password import md5_password 27 from apachelib.password import md5_password
27 return md5_password(passwd) 28 return md5_password(passwd)
28 29
29 # We should never get here 30 # We should never get here
30 raise ValueError("%s is not a valid value for ctype." % ctype) 31 raise ValueError("%s is not a valid value for ctype." % ctype)
31 32
33
32def generate_user(username, passwd, ctype="crypt"): 34def generate_user(username, passwd, ctype="crypt"):
33 """Generate a single htaccess line. 35 """Generate a single htaccess line.
34 """ 36 """
diff --git a/md5.py b/md5.py
index 917612e..0098c56 100755
--- a/md5.py
+++ b/md5.py
@@ -12,7 +12,7 @@ little bit wierd.
12 12
13This is a pythonic adaption of the C code in the APR library. 13This is a pythonic adaption of the C code in the APR library.
14If there are any questions please refer directly to the C code. 14If there are any questions please refer directly to the C code.
15You'll find it in apache subversion under 15You'll find it in apache subversion under
16/ap/apr-util/crypto/apr_md5.c 16/ap/apr-util/crypto/apr_md5.c
17""" 17"""
18 18
@@ -21,11 +21,12 @@ from hashlib import md5
21from random import random 21from random import random
22from math import floor 22from math import floor
23 23
24__all__ = [ "generate_md5", "generate_salt", "generate_short_salt" ] 24__all__ = ["generate_md5", "generate_salt", "generate_short_salt"]
25 25
26# Defined as such for brevity 26# Defined as such for brevity
27md5digest = lambda x: md5(x).digest() 27md5digest = lambda x: md5(x).digest()
28 28
29
29def ap_to64(input, count=4): 30def ap_to64(input, count=4):
30 """Weird-ass implementation of base64 conversion used by the 31 """Weird-ass implementation of base64 conversion used by the
31 APR library. 32 APR library.
@@ -33,19 +34,21 @@ def ap_to64(input, count=4):
33 chars = "./0123456789%s%s" % (string.uppercase, string.lowercase) 34 chars = "./0123456789%s%s" % (string.uppercase, string.lowercase)
34 output = "" 35 output = ""
35 input = int(input) # Need ints to do binary math 36 input = int(input) # Need ints to do binary math
36 37
37 for i in range(0, count): 38 for i in range(0, count):
38 output += chars[input & 0x3f] # Take 6 bits right 39 output += chars[input & 0x3f] # Take 6 bits right
39 input >>= 6 # shift by 6 bits 40 input >>= 6 # shift by 6 bits
40 41
41 return output 42 return output
42 43
44
43def generate_short_salt(): 45def generate_short_salt():
44 """Generate a short, 2-character salt. 46 """Generate a short, 2-character salt.
45 This is suitable for use in the htpasswd crypt routine. 47 This is suitable for use in the htpasswd crypt routine.
46 """ 48 """
47 return generate_salt()[0:2] 49 return generate_salt()[0:2]
48 50
51
49def generate_salt(): 52def generate_salt():
50 """Mine a little salt for your passwords. 53 """Mine a little salt for your passwords.
51 Returns 8 random characters in base64. It is 4 + 4 because the original 54 Returns 8 random characters in base64. It is 4 + 4 because the original
@@ -55,6 +58,7 @@ def generate_salt():
55 salt += ap_to64(floor(random() * 16777215)) 58 salt += ap_to64(floor(random() * 16777215))
56 return salt 59 return salt
57 60
61
58def generate_md5(passwd, salt=None): 62def generate_md5(passwd, salt=None):
59 """Generate an APRfied MD5 hash. 63 """Generate an APRfied MD5 hash.
60 This was adapted directly from the C code in the APR library. 64 This was adapted directly from the C code in the APR library.
@@ -66,10 +70,10 @@ def generate_md5(passwd, salt=None):
66 # I don't think it is really "checked" by Apache but I'm too 70 # I don't think it is really "checked" by Apache but I'm too
67 # lazy to confirm this. 71 # lazy to confirm this.
68 MAGIC_TOKEN = "$apr1$" 72 MAGIC_TOKEN = "$apr1$"
69 73
70 # Mainly just used for testing but why not leave it? 74 # Mainly just used for testing but why not leave it?
71 salt = salt if salt else generate_salt() 75 salt = salt if salt else generate_salt()
72 76
73 # Start with our password in the clear, a little magic and 77 # Start with our password in the clear, a little magic and
74 # a pinch of salt 78 # a pinch of salt
75 message = "%s%s%s" % (passwd, MAGIC_TOKEN, salt) 79 message = "%s%s%s" % (passwd, MAGIC_TOKEN, salt)
@@ -89,21 +93,21 @@ def generate_md5(passwd, salt=None):
89 message += chr(0) 93 message += chr(0)
90 else: 94 else:
91 message += passwd[0] 95 message += passwd[0]
92 passlen >>= 1 96 passlen >>= 1
93 97
94 retval = md5digest(message) 98 retval = md5digest(message)
95 99
96 for i in range(0, 1000): 100 for i in range(0, 1000):
97 if i & 1: 101 if i & 1:
98 message = passwd 102 message = passwd
99 else: 103 else:
100 message = retval[0:16] 104 message = retval[0:16]
101 105
102 if i % 3: 106 if i % 3:
103 message += salt 107 message += salt
104 108
105 if i % 7: 109 if i % 7:
106 message += passwd 110 message += passwd
107 111
108 if i & 1: 112 if i & 1:
109 message += retval[0:16] 113 message += retval[0:16]
@@ -111,7 +115,7 @@ def generate_md5(passwd, salt=None):
111 message += passwd 115 message += passwd
112 116
113 retval = md5digest(message) 117 retval = md5digest(message)
114 118
115 # Now make the output string 119 # Now make the output string
116 output = ap_to64((ord(retval[0]) << 16) | (ord(retval[6]) << 8) | ord(retval[12])) 120 output = ap_to64((ord(retval[0]) << 16) | (ord(retval[6]) << 8) | ord(retval[12]))
117 output += ap_to64((ord(retval[1]) << 16) | (ord(retval[7]) << 8) | ord(retval[13])) 121 output += ap_to64((ord(retval[1]) << 16) | (ord(retval[7]) << 8) | ord(retval[13]))
@@ -122,6 +126,7 @@ def generate_md5(passwd, salt=None):
122 126
123 return "%s%s$%s" % (MAGIC_TOKEN, salt, output) 127 return "%s%s$%s" % (MAGIC_TOKEN, salt, output)
124 128
129
125def test_driver(): 130def test_driver():
126 """Run this to verify that the library is functioning properly. 131 """Run this to verify that the library is functioning properly.
127 This one test case should be enough to verify the functionality. 132 This one test case should be enough to verify the functionality.
diff --git a/password.py b/password.py
index 3570cf4..fe861e0 100644..100755
--- a/password.py
+++ b/password.py
@@ -10,6 +10,7 @@ Algorithm information was collected for various sources around the web
10and from analysis of the APR C code. 10and from analysis of the APR C code.
11""" 11"""
12 12
13
13def crypt_password(passwd): 14def crypt_password(passwd):
14 """Generate Apache-style CRYPT password hash. 15 """Generate Apache-style CRYPT password hash.
15 """ 16 """
@@ -17,6 +18,7 @@ def crypt_password(passwd):
17 from apachelib.md5 import generate_short_salt 18 from apachelib.md5 import generate_short_salt
18 return crypt(passwd, generate_short_salt()) 19 return crypt(passwd, generate_short_salt())
19 20
21
20def sha_password(passwd): 22def sha_password(passwd):
21 """Generate Apache-style SHA1 password hash. 23 """Generate Apache-style SHA1 password hash.
22 """ 24 """
@@ -24,8 +26,9 @@ def sha_password(passwd):
24 from base64 import b64encode 26 from base64 import b64encode
25 return "{SHA}%s" % b64encode(sha1(passwd).digest()) 27 return "{SHA}%s" % b64encode(sha1(passwd).digest())
26 28
29
27def md5_password(passwd): 30def md5_password(passwd):
28 """Generate Apache-style MD5 password hash. 31 """Generate Apache-style MD5 password hash.
29 """ 32 """
30 from apachelib.md5 import generate_md5 33 from apachelib.md5 import generate_md5
31 return generate_md5(passwd) 34 return generate_md5(passwd)