[Zope-Checkins] CVS: ZODB3/ZEO/auth - .cvsignore:1.1.2.1 __init__.py:1.1.2.1 auth_plaintext.py:1.1.2.1 auth_sha.py:1.1.2.1 database.py:1.1.2.1 hmac.py:1.1.2.1 storage.py:1.1.2.1
Johan Dahlin
jdahlin@telia.com
Tue, 29 Apr 2003 16:02:55 -0400
Update of /cvs-repository/ZODB3/ZEO/auth
In directory cvs.zope.org:/tmp/cvs-serv23889/auth
Added Files:
Tag: ZODB3-auth-branch
.cvsignore __init__.py auth_plaintext.py auth_sha.py
database.py hmac.py storage.py
Log Message:
Initial checkin of AuthZEO (without SRP)
=== Added File ZODB3/ZEO/auth/.cvsignore ===
*.pyo
*.pyc
=== Added File ZODB3/ZEO/auth/__init__.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
=== Added File ZODB3/ZEO/auth/auth_plaintext.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Implements plaintext password authentication. The password is stored in
an SHA hash in the Database. The client sends over the plaintext
password, and the SHA hashing is done on the server side.
This mechanism offers *no network security at all*; the only security
is provided by not storing plaintext passwords on disk. (See the
auth_srp module for a secure mechanism)"""
import sha
from ZEO.auth.storage import AuthZEOStorage
class StorageClass(AuthZEOStorage):
def auth(self, username, password):
try:
dbpw = self.database.get_password(username)
except LookupError:
return 0
password = sha.new(password).hexdigest()
return self.finish_auth(dbpw == password)
class Client:
def __init__(self, stub):
self.stub = stub
def start(self, username, password):
method = self.stub.extensionMethod('auth')
return method(username, password)
=== Added File ZODB3/ZEO/auth/auth_sha.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Implements simple hashed password authentication. The password is stored in
an SHA hash in the Database. The client sends over the hashed password,
which is verified by the server.
This mechanism offers *very weak network security*; the password
hash is capturable and the mechanism is vulnerable to trivial replay
attacks. (See the auth_srp module for a secure mechanism)"""
import sha
from ZEO.auth.storage import AuthZEOStorage
class StorageClass(AuthZEOStorage):
def auth(self, username, password):
try:
dbpw = self.database.get_password(username)
except LookupError:
return 0
return self.finish_auth(dbpw == password)
class Client:
def __init__(self, stub):
self.stub = stub
def start(self, username, password):
method = self.stub.extensionMethod('auth')
return method(username, sha.new(password).hexdigest())
=== Added File ZODB3/ZEO/auth/database.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import os
import sha
from types import StringType
class Database:
"""Abstracts a password database. This class is used both in the
authentication process (via get_password()) and by client scripts
that manage the password database file.
The password file is a simple, colon-separated text file mapping
usernames to password hashes. The hashes are SHA hex digests
produced from the password string."""
def __init__(self, filename):
"""Creates a new Database
filename: a string containing the full pathname of
the password database file. Must be readable by the user
running ZEO. Must be writeable by any client script that
accesses the database."""
self._users = {}
self.filename = filename
self.load()
def save(self, fd=None):
filename = self.filename
if not fd:
fd = open(filename, 'w')
for username, hash in self._users.items():
fd.write('%s:%s\n' % (username, hash))
def load(self):
filename = self.filename
if not filename:
return
if not os.path.exists(filename):
return
fd = open(filename)
for line in fd.readlines():
username, hash = line[:-1].split(':', 1)
self._users[username] = hash
def _store_password(self, username, password):
if type(password) <> StringType:
raise TypeError, "password must be a string"
self._users[username] = self.hash(password)
def get_password(self, username):
"""Returns password hash for specified username.
Callers must check for LookupError, which is raised in
the case of a non-existent user specified."""
if not self._users.has_key(username):
raise LookupError, "No such user: %s" % username
return self._users[username]
def hash(self, s):
return sha.new(s).hexdigest()
def add_user(self, username, password):
if self._users.has_key(username):
raise LookupError, "User %s does already exist" % username
if type(username) <> StringType:
raise TypeError, "username must be a string"
self._store_password(username, password)
def del_user(self, username):
if not self._users.has_key(username):
raise LookupError, "No such user: %s" % username
del self._users[username]
def change_password(self, username, password):
if not self._users.has_key(username):
raise LookupError, "No such user: %s" % username
self._store_password(username, password)
=== Added File ZODB3/ZEO/auth/hmac.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""HMAC -- keyed hashing for message authentication, as described in rfc2104.
Author: Tom Holroyd <tomh@kurage.nimh.nih.gov>
Part of the SRPSocket package:
http://members.tripod.com/professor_tom/archives/srpsocket.html
"""
import sha
BLEN = 64
ipad = map(ord, "\x36" * BLEN)
opad = map(ord, "\x5C" * BLEN)
def hash(s):
return sha.new(s).digest()
def hmac(key, text):
"""Given strings 'key' and 'text', produce an HMAC digest."""
# If the key is longer than BLEN, hash it first. The result must
# be less than BLEN bytes. This depends on the hash function used;
# sha1 and md5 are both OK.
l = len(key)
if l > BLEN:
key = hash(key)
l = len(key)
# Pad the key with zeros to BLEN bytes.
key = key + '\0' * (BLEN - l)
key = map(ord, key)
# Now compute the HMAC.
l = map(lambda x, y: x ^ y, key, ipad)
s = reduce(lambda x, y: x + chr(y), l, '')
s = hash(s + text)
l = map(lambda x, y: x ^ y, key, opad)
t = reduce(lambda x, y: x + chr(y), l, '')
s = hash(t + s)
return s
=== Added File ZODB3/ZEO/auth/storage.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
from ZEO.Exceptions import AuthError
from ZEO.StorageServer import ZEOStorage
class AuthZEOStorage(ZEOStorage):
def __init_(self, *args, **kwargs):
ZEOStorage.__init__(self, *args, **kwargs)
self.authenticated = 0
def set_database(self, database):
self.database = database
def finish_auth(self, authenticated):
self.authenticated = authenticated
return authenticated
def register(self, storage_id, read_only):
if not self.authenticated:
raise AuthError, "Client was never authenticated with server!"
ZEOStorage.register(self, storage_id, read_only)