Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZODB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Nicolas Wavrant
ZODB
Commits
7e1fe222
Commit
7e1fe222
authored
Apr 29, 2003
by
John Dahlin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial checkin of AuthZEO (without SRP)
parent
7e7f38b2
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
347 additions
and
10 deletions
+347
-10
src/ZEO/ClientStorage.py
src/ZEO/ClientStorage.py
+52
-3
src/ZEO/Exceptions.py
src/ZEO/Exceptions.py
+2
-0
src/ZEO/ServerStub.py
src/ZEO/ServerStub.py
+4
-1
src/ZEO/StorageServer.py
src/ZEO/StorageServer.py
+74
-3
src/ZEO/runzeo.py
src/ZEO/runzeo.py
+7
-3
src/ZEO/tests/testAuth.py
src/ZEO/tests/testAuth.py
+101
-0
src/ZEO/zpasswd.py
src/ZEO/zpasswd.py
+107
-0
No files found.
src/ZEO/ClientStorage.py
View file @
7e1fe222
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# Copyright (c) 2001, 2002
, 2003
Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
...
...
@@ -29,7 +29,8 @@ import types
from
ZEO
import
ClientCache
,
ServerStub
from
ZEO.TransactionBuffer
import
TransactionBuffer
from
ZEO.Exceptions
\
import
ClientStorageError
,
UnrecognizedResult
,
ClientDisconnected
import
ClientStorageError
,
UnrecognizedResult
,
ClientDisconnected
,
\
AuthError
from
ZEO.zrpc.client
import
ConnectionManager
from
ZODB
import
POSException
...
...
@@ -99,7 +100,8 @@ class ClientStorage:
min_disconnect_poll
=
5
,
max_disconnect_poll
=
300
,
wait_for_server_on_startup
=
None
,
# deprecated alias for wait
wait
=
None
,
# defaults to 1
read_only
=
0
,
read_only_fallback
=
0
):
read_only
=
0
,
read_only_fallback
=
0
,
username
=
''
,
password
=
''
):
"""ClientStorage constructor.
...
...
@@ -159,6 +161,17 @@ class ClientStorage:
writable storages are available. Defaults to false. At
most one of read_only and read_only_fallback should be
true.
username -- string with username to be used when authenticating.
These only need to be provided if you are connecting to an
authenticated server storage.
password -- string with plaintext password to be used
when authenticated.
Note that the authentication scheme is defined by the server and is
detected by the ClientStorage upon connecting (see testConnection()
and doAuth() for details).
"""
log2
(
INFO
,
"%s (pid=%d) created %s/%s for storage: %r"
%
...
...
@@ -217,6 +230,8 @@ class ClientStorage:
self
.
_conn_is_read_only
=
0
self
.
_storage
=
storage
self
.
_read_only_fallback
=
read_only_fallback
self
.
_username
=
username
self
.
_password
=
password
# _server_addr is used by sortKey()
self
.
_server_addr
=
None
self
.
_tfile
=
None
...
...
@@ -347,6 +362,34 @@ class ClientStorage:
if
cn
is
not
None
:
cn
.
pending
()
def
doAuth
(
self
,
protocol
,
stub
):
if
self
.
_username
==
''
and
self
.
_password
==
''
:
raise
AuthError
,
"empty username or password"
# import the auth module
# XXX: Should we validate the client module that is being specified
# by the server? A malicious server could cause any auth_*.py file
# to be loaded according to Python import semantics.
fullname
=
'ZEO.auth.auth_'
+
protocol
try
:
module
=
__import__
(
fullname
,
globals
(),
locals
(),
protocol
)
except
ImportError
:
log
(
"%s: no such an auth protocol: %s"
%
(
self
.
__class__
.
__name__
,
protocol
))
# And setup ZEOStorageClass
Client
=
getattr
(
module
,
'Client'
,
None
)
if
not
Client
:
log
(
"%s: %s is not a valid auth protocol, must have a "
+
\
"Client class"
%
(
self
.
__class__
.
__name__
,
protocol
))
raise
AuthError
,
"invalid protocol"
c
=
Client
(
stub
)
# Initiate authentication, return boolean specifying whether OK or not
return
c
.
start
(
self
.
_username
,
self
.
_password
)
def
testConnection
(
self
,
conn
):
"""Internal: test the given connection.
...
...
@@ -372,6 +415,12 @@ class ClientStorage:
# XXX Check the protocol version here?
self
.
_conn_is_read_only
=
0
stub
=
self
.
StorageServerStubClass
(
conn
)
# XXX: Verify return value
auth
=
stub
.
getAuthProtocol
()
if
auth
and
not
self
.
doAuth
(
auth
,
stub
):
raise
AuthError
,
"Authentication failed"
try
:
stub
.
register
(
str
(
self
.
_storage
),
self
.
_is_read_only
)
return
1
...
...
src/ZEO/Exceptions.py
View file @
7e1fe222
...
...
@@ -24,3 +24,5 @@ class UnrecognizedResult(ClientStorageError):
class
ClientDisconnected
(
ClientStorageError
):
"""The database storage is disconnected from the storage."""
class
AuthError
(
StorageError
):
"""The client provided invalid authentication credentials."""
src/ZEO/ServerStub.py
View file @
7e1fe222
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# Copyright (c) 2001, 2002
, 2003
Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
...
...
@@ -45,6 +45,9 @@ class StorageServer:
def
get_info
(
self
):
return
self
.
rpc
.
call
(
'get_info'
)
def
getAuthProtocol
(
self
):
return
self
.
rpc
.
call
(
'getAuthProtocol'
)
def
lastTransaction
(
self
):
# Not in protocol version 2.0.0; see __init__()
return
self
.
rpc
.
call
(
'lastTransaction'
)
...
...
src/ZEO/StorageServer.py
View file @
7e1fe222
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# Copyright (c) 2001, 2002
, 2003
Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
...
...
@@ -31,6 +31,7 @@ import time
from
ZEO
import
ClientStub
from
ZEO.CommitLog
import
CommitLog
from
ZEO.auth.database
import
Database
from
ZEO.monitor
import
StorageStats
,
StatsServer
from
ZEO.zrpc.server
import
Dispatcher
from
ZEO.zrpc.connection
import
ManagedServerConnection
,
Delay
,
MTDelay
...
...
@@ -161,6 +162,8 @@ class ZEOStorage:
"""Select the storage that this client will use
This method must be the first one called by the client.
For authenticated storages this method will be called by the client
immediately after authentication is finished.
"""
if
self
.
storage
is
not
None
:
self
.
log
(
"duplicate register() call"
)
...
...
@@ -410,6 +413,15 @@ class ZEOStorage:
else
:
return
self
.
_wait
(
lambda
:
self
.
_vote
())
def
getAuthProtocol
(
self
):
"""Return string specifying name of authentication module to use.
The module name should be auth_%s where %s is auth_protocol."""
protocol
=
self
.
server
.
auth_protocol
if
not
protocol
or
protocol
==
'none'
:
return
None
return
protocol
def
abortVersion
(
self
,
src
,
id
):
self
.
_check_tid
(
id
,
exc
=
StorageTransactionError
)
if
self
.
locked
:
...
...
@@ -577,7 +589,9 @@ class StorageServer:
def
__init__
(
self
,
addr
,
storages
,
read_only
=
0
,
invalidation_queue_size
=
100
,
transaction_timeout
=
None
,
monitor_address
=
None
):
monitor_address
=
None
,
auth_protocol
=
None
,
auth_filename
=
None
):
"""StorageServer constructor.
This is typically invoked from the start.py script.
...
...
@@ -618,7 +632,22 @@ class StorageServer:
monitor_address -- The address at which the monitor server
should listen. If specified, a monitor server is started.
The monitor server provides server statistics in a simple
text format.
text format.
auth_protocol -- The name of the authentication protocol to use.
Examples are "plaintext", "sha" and "srp".
auth_filename -- The name of the password database filename.
It should be in a format compatible with the authentication
protocol used; for instance, "sha" and "srp" require different
formats.
Note that to implement an authentication protocol, a server
and client authentication mechanism must be implemented in a
auth_* module, which should be stored inside the "auth"
subdirectory. This module may also define a DatabaseClass
variable that should indicate what database should be used
by the authenticator.
"""
self
.
addr
=
addr
...
...
@@ -633,6 +662,10 @@ class StorageServer:
for
s
in
storages
.
values
():
s
.
_waiting
=
[]
self
.
read_only
=
read_only
self
.
auth_protocol
=
auth_protocol
self
.
auth_filename
=
auth_filename
if
auth_protocol
:
self
.
_setup_auth
(
auth_protocol
)
# A list of at most invalidation_queue_size invalidations
self
.
invq
=
[]
self
.
invq_bound
=
invalidation_queue_size
...
...
@@ -654,7 +687,43 @@ class StorageServer:
self
.
monitor
=
StatsServer
(
monitor_address
,
self
.
stats
)
else
:
self
.
monitor
=
None
def
_setup_auth
(
self
,
protocol
):
# Load the auth protocol
fullname
=
'ZEO.auth.auth_'
+
protocol
try
:
module
=
__import__
(
fullname
,
globals
(),
locals
(),
protocol
)
except
ImportError
:
log
(
"%s: no such an auth protocol: %s"
%
(
self
.
__class__
.
__name__
,
protocol
))
self
.
auth_protocol
=
None
return
from
ZEO.auth.storage
import
AuthZEOStorage
# And set up ZEOStorageClass
klass
=
getattr
(
module
,
'StorageClass'
,
None
)
if
not
klass
or
not
issubclass
(
klass
,
AuthZEOStorage
):
log
((
"%s: %s is not a valid auth protocol, must have a "
+
\
"StorageClass class"
)
%
(
self
.
__class__
.
__name__
,
protocol
))
self
.
auth_protocol
=
None
return
self
.
ZEOStorageClass
=
klass
log
(
"%s: using auth protocol: %s"
%
\
(
self
.
__class__
.
__name__
,
protocol
))
dbklass
=
getattr
(
module
,
'DatabaseClass'
,
None
)
if
not
dbklass
:
dbklass
=
Database
# We create a Database instance here for use with the authenticator
# modules. Having one instance allows it to be shared between multiple
# storages, avoiding the need to bloat each with a new authenticator
# Database that would contain the same info, and also avoiding any
# possibly synchronization issues between them.
self
.
database
=
dbklass
(
self
.
auth_filename
)
def
new_connection
(
self
,
sock
,
addr
):
"""Internal: factory to create a new connection.
...
...
@@ -663,6 +732,8 @@ class StorageServer:
connection.
"""
z
=
self
.
ZEOStorageClass
(
self
,
self
.
read_only
)
if
self
.
auth_protocol
:
z
.
set_database
(
self
.
database
)
c
=
self
.
ManagedServerConnectionClass
(
sock
,
addr
,
z
,
self
)
log
(
"new connection %s: %s"
%
(
addr
,
`c`
))
return
c
...
...
src/ZEO/runzeo.py
View file @
7e1fe222
#!python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# Copyright (c) 2001, 2002
, 2003
Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
...
...
@@ -89,7 +89,9 @@ class ZEOOptionsMixin:
"t:"
,
"timeout="
,
float
)
self
.
add
(
"monitor_address"
,
"zeo.monitor_address"
,
"m:"
,
"monitor="
,
self
.
handle_monitor_address
)
self
.
add
(
'auth_protocol'
,
'zeo.auth_protocol'
,
None
,
'auth-protocol='
,
default
=
None
)
self
.
add
(
'auth_filename'
,
'zeo.auth_filename'
,
None
,
'auth-filename='
)
class
ZEOOptions
(
ZDOptions
,
ZEOOptionsMixin
):
...
...
@@ -189,7 +191,9 @@ class ZEOServer:
read_only
=
self
.
options
.
read_only
,
invalidation_queue_size
=
self
.
options
.
invalidation_queue_size
,
transaction_timeout
=
self
.
options
.
transaction_timeout
,
monitor_address
=
self
.
options
.
monitor_address
)
monitor_address
=
self
.
options
.
monitor_address
,
auth_protocol
=
self
.
options
.
auth_protocol
,
auth_filename
=
self
.
options
.
auth_filename
)
def
loop_forever
(
self
):
import
ThreadedAsync.LoopCallback
...
...
src/ZEO/tests/testAuth.py
0 → 100644
View file @
7e1fe222
##############################################################################
#
# Copyright (c) 2001, 2002 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
#
##############################################################################
"""Test suite for AuthZEO."""
import
glob
import
os
import
time
import
unittest
from
ThreadedAsync
import
LoopCallback
from
ZEO.auth.database
import
Database
#from ZEO.auth.auth_srp import SRPDatabase
from
ZEO.ClientStorage
import
ClientStorage
from
ZEO.StorageServer
import
StorageServer
from
ZODB.FileStorage
import
FileStorage
storage
=
FileStorage
(
'auth-test.fs'
)
SOCKET
=
'auth-test-socket'
STORAGES
=
{
'1'
:
storage
}
class
BaseTest
(
unittest
.
TestCase
):
def
createDB
(
self
,
name
):
if
os
.
path
.
exists
(
name
):
os
.
remove
(
self
.
database
)
if
name
.
endswith
(
'srp'
):
db
=
SRPDatabase
(
name
)
else
:
db
=
Database
(
name
)
db
.
add_user
(
'foo'
,
'bar'
)
db
.
save
()
def
setUp
(
self
):
self
.
createDB
(
self
.
database
)
self
.
pid
=
os
.
fork
()
if
not
self
.
pid
:
self
.
server
=
StorageServer
(
SOCKET
,
STORAGES
,
auth_protocol
=
self
.
protocol
,
auth_filename
=
self
.
database
)
LoopCallback
.
loop
()
def
tearDown
(
self
):
os
.
kill
(
self
.
pid
,
9
)
os
.
remove
(
self
.
database
)
os
.
remove
(
SOCKET
)
for
file
in
glob
.
glob
(
'auth-test.fs*'
):
os
.
remove
(
file
)
def
check
(
self
):
# Sleep for 0.2 seconds to give the server some time to start up
# seems to be needed before and after creating the storage
time
.
sleep
(
0.2
)
cs
=
ClientStorage
(
SOCKET
,
wait
=
0
,
username
=
'foo'
,
password
=
'bar'
)
time
.
sleep
(
0.2
)
if
cs
.
_connection
==
None
:
raise
AssertionError
,
\
"authentication for %s failed"
%
self
.
protocol
cs
.
_connection
.
poll
()
if
not
cs
.
is_connected
():
raise
AssertionError
,
\
"authentication for %s failed"
%
self
.
protocol
class
PlainTextAuth
(
BaseTest
):
protocol
=
'plaintext'
database
=
'authdb.sha'
class
SHAAuth
(
BaseTest
):
protocol
=
'sha'
database
=
'authdb.sha'
#class SRPAuth(BaseTest):
# protocol = 'srp'
# database = 'authdb.srp'
test_classes
=
[
PlainTextAuth
,
SHAAuth
]
# SRPAuth
def
test_suite
():
suite
=
unittest
.
TestSuite
()
for
klass
in
test_classes
:
sub
=
unittest
.
makeSuite
(
klass
,
'check'
)
suite
.
addTest
(
sub
)
return
suite
if
__name__
==
"__main__"
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
src/ZEO/zpasswd.py
0 → 100644
View file @
7e1fe222
##############################################################################
#
# 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
#
##############################################################################
"""Usage:
zpasswd [-cd] passwordfile username
zpasswd -b[cd] passwordfile username password
zpasswd -n[d] username
zpasswd -nb[d] username password
-c Create a new file.
-d Delete user
-n Don't update file; display results on stdout.
-b Use the password from the command line rather than prompting for it."""
import
sys
import
getopt
import
getpass
from
ZEO.auth.database
import
Database
#from ZEO.auth.srp import SRPDatabase
try
:
opts
,
args
=
getopt
.
getopt
(
sys
.
argv
[
1
:],
'cdnbs'
)
except
getopt
.
GetoptError
:
# print help information and exit:
print
__doc__
sys
.
exit
(
2
)
stdout
=
0
create
=
0
delete
=
0
prompt
=
1
#srp = 0
for
opt
,
arg
in
opts
:
if
opt
in
(
"-h"
,
"--help"
):
print
__doc__
sys
.
exit
()
if
opt
==
"-n"
:
stdout
=
1
if
opt
==
"-c"
:
create
=
1
if
opt
==
"-d"
:
delete
=
1
if
opt
==
"b"
:
prompt
=
0
# if opt == "-s":
# srp = 1
if
create
and
delete
:
print
"Can't create and delete at the same time"
sys
.
exit
(
3
)
if
len
(
args
)
<
2
:
print
__doc__
sys
.
exit
()
output
=
args
[
0
]
username
=
args
[
1
]
if
not
delete
:
if
len
(
args
)
>
3
:
print
__doc__
sys
.
exit
()
if
prompt
:
password
=
getpass
.
getpass
(
'Enter passphrase: '
)
else
:
password
=
args
[
2
]
#if srp:
# db = SRPDatabase(output)
#else:
db
=
Database
(
output
)
if
create
:
try
:
db
.
add_user
(
username
,
password
)
except
LookupError
:
print
'The username already exists'
sys
.
exit
(
4
)
if
stdout
:
db
.
save
(
fd
=
sys
.
stdout
)
else
:
db
.
save
()
if
delete
:
try
:
db
.
del_user
(
username
)
except
LockupError
:
print
'The username doesn
\
'
t exist'
sys
.
exit
(
5
)
if
stdout
:
db
.
save
(
fd
=
sys
.
stdout
)
else
:
db
.
save
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment