<previous | contents | next> | Pyro Manual |
Pyro.protocol.DefaultConnValidator
.
The fun is that you can supply your own validator object, and that you can therefore implement much more complex access checks. For instance, you might want
to check if the client's site is authorized to connect. Or perhaps you require a password to connect.
Enter authentication validation. This means that a client that wants to connect to your Pyro server needs to supply a valid authentication passphrase, or the connection is denied. The check takes place automatically (it is performed by the default connection validator), at connect time. The following items are important:
Look at the "denyhosts" and "authenticate" examples to see how you can use the connection validators.
PYRO_MAXCONNECTIONS
configuration item. This limit is always checked when a new client connects.
To enable passphrase authentication, you must tell the Pyro Daemon a list of accepted passphrases.
Do this by calling the setAllowedIdentifications(ids)
method of the daemon, where ids
is
a list of passphrases (strings). If you use None
for this, the authentication is disabled again.
To specify for your client what passphrase to use for a specific object, call the proxy._setIdentification(id)
method of the Pyro proxy, where id
is your passphrase (string). Use Null
to disable authentication again.
Call the method right after you obtained the proxy using getProxyForURI
or whatever.
If a connection is denied, Pyro will raise a ConnectionDeniedError
, otherwise the
connection is granted and your client proxy can invoke any methods it likes, untill disconnected.
Pyro.protocol.BasicSSLValidator
is used by default.
This is an extension to the normal validator, it also checks if the client has supplied
a SSL certificate. See the "ssl" example for details.
Pyro.protocol.DefaultConnValidator
(recommended).
If you want to create your own, have a look at how the default validator works. The instructions below
are for a custom connection validator that extends the default validator.
Pyro.protocol.DefaultConnValidator
and call its __init__()
in your own init (no arguments, required step!).
acceptHost(self,daemon,connection)
method that is called to check
the clients origin. The daemon
is the current Pyro daemon, connection
is a Pyro.protocol.TCPConnection
object. The client's socket address is in connection.addr
.
You can check the client's IP address for instance, to see if it is in a trusted range.
The default implementation of this method checks if the number of active connections has not reached the limit.
acceptIdentification(self, daemon, connection, hash, challenge)
method that is called to check
if a client supplied a valid authentication passphrase. daemon
and connection
are the same as above, hash
is the binary md5 hash (digest) of the client's passphrase.
challenge
is the challenge string that was generated by the server and must
be joined with the passphrase to check the actual auth id.
The default implementation of this method checks if the client-supplied hash is among the accepted
passphrases of the daemon (digest of passphrase+challenge) -- if any are specified, otherwise it is just accepted. Have a look at the code for exact details on this.
Pyro.protocol.BasicSSLValidator
(for SSL connections),
you can override the checkCertificate(self, cert)
method. cert
is the
SSL certificate that the client provides. Note: this method is called from the
acceptHost
method, so you must leave that one as-is or call the base class
implmentation of that method if you override it.
(1,0)
if the connection is accepted,
or (0,code)
when the connection is refused, where code
is one of the following:
Deny Reason Code | Description |
---|---|
Pyro.constants.DENIED_UNSPECIFIED | unspecified |
Pyro.constants.DENIED_SERVERTOOBUSY | server too busy (too many connections) |
Pyro.constants.DENIED_HOSTBLOCKED | host blocked |
Pyro.constants.DENIED_SECURITY | security reasons (general) |
Pyro will raise the appropriate ConnectionDeniedError
on the client when you deny a new connection. On the server, you'll have to log the reason in the Pyro logfile yourself, if desired. When you accept a connection, the daemon will log an entry for you.
setAllowedIdentifications(self, ids)
that is used to
set the list of allowed authorization ids. It probably isn't interesting to override. It stores a
list of binary md5 hashes (digests) of the ids in self.allowedIDs
.
setNewConnectionValidator
method. Supply an instance
of your validator class as an argument.
setAllowedIdentifications
on your Daemon, to set the list of allowed identification strings, and to enable
the passphrase identification.
BCGuard()
function that returns a BC request validator object, or None
.
NSGuard()
function that returns a NS new conn validator object, or None
.
Pyro.naming.BCReqValidator
. You must override the two
methods that check for each command if it is allowed or if it is refused.
These are acceptLocationCmd(self)
and acceptShutdownCmd(self)
, and they return 0 or 1 (accept or deny).
You can access self.addr
to have the client's address (ip,port).
You can call self.reply('message')
to send a message back to
the client. This may be polite, to let it know why you refused the command.
This codeValidator is a function (or callable object) that takes three arguments: the name of the module, the code itself, and the address of the client (usually a (IP,port) tuple). It should return 0 or 1, for 'deny' and 'accept'.
Pyro.core.ObjBase
, the base class of all Pyro objects, has a
setCodeValidator(v)
method that you must call with your custom
validator function (or callable object). You can set a different validator
for each Pyro object that your server has.
pickle
protocol to pass calls to remote objects.
There is a security problem with pickle
: it is possible to execute arbitrary
code on the server by passing an artificially constructed pickled string message.
The standard Python Cookie
module also suffers from this problem.
At the moment of writing, the Python documentation is not clear on this subject.
The problem is known to various people.
Using Pyro over the internet could expose your server to this vulnerability!!!!
Using the (safe) marshal
module is no option
for Pyro because we lose the ability to serialize user defined objects.
But, if you accept a performance penalty of an order of a magnitude, and
more required bandwith (2-4 times more), you can choose to
use the safe XML pickling from PyXML or Gnosis_Utils.
To enable this, set the PYRO_XML_PICKLE
config item to "any" for any implementation
(defaults to PyXML), "pyxml" for PyXML, or "gnosis" for Gnosis tools. You need to have the appropriate package installed
otherwise Pyro won't start. The server will answer in XML pickled messages also,
regardless of the server's PYRO_XML_PICKLE
setting. So make sure that the correct XML packages are installed on both ends of the communication.
If the server is configured to use PYRO_XML_PICKLE
, it will only accept XML pickled requests!
Please note that at least since Python 2.2 a few pickle security flaws
appear to have been removed, and the obvious trojan exploit with pickle no longer works on Python 2.2+. But still, do you trust pickle? ;-)
Use PYRO_XML_PICKLE
if you want to be safe.
To start using SSL, you need to tell your Pyro daemon that it must use
SSL instead of regular sockets. Do that by passing a prtcol
parameter
when you create a daemon, as follows:
daemon = Pyro.core.Daemon(prtcol='PYROSSL')(the
prtcol
defaults to 'PYRO' ofcourse).
All Pyro objects connected to this daemon will get registered in the Name Server
using the special PYROSSL protocol, that tells Pyro to use SSL instead of regular sockets.
You may also want to add a special SSL connection validator on your daemon that checks
the client certificate.
The client programs don't need any changes because Pyro knows automatically
how to deal with the PYROSSL protocol.
There are a few configuration items that deal with the SSL configuration,
look for PYROSSL_CERTDIR
and the other items starting
with PYROSSL
.
See the M2Crypto homepage
or OpenSSL documentation for instructions on how to
create your own Certificate Authority- and server/client certificates.
See the "ssl" example for more info.
<previous | contents | next> | Pyro Manual |