<previous | contents | next> Pyro Manual

9. Security

This chapter discusses the security aspects of Pyro, the features you can use to control security, and some important warnings.

Connection validators

To guard against unwanted or unauthorized connections, Pyro uses so-called new connection validators. These are objects that are called to check whether a Pyro server may or may not accept a new connection that a client tries to make. By default, there is only one built-in check; the number of connections was limited to a certain amount specifed in the PYRO_MAXCONNECTIONS config item). This check is done by the default connection validator 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.

Pyro 3.0 introduced 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:

The Name Server and the Event Server can both be instructed to require authentication too. See the chapters for each server for more information on how to configure this.

Look at the "denyhosts" and "authenticate" examples to see how you can use the connection validators.

How to use the default connection Validator

You can specify the maximum number of connections that Pyro accepts by setting the 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.

The default SSL connection Validator

For SSL connections, the 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.

How to implement a custom validator that does even more

You can roll your own validator, or extend the default connection validator 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.

Name Server security plugins

The Name Server supports security plugins, to facilitate access control to the Name Server. Different options are available: You'll have to write a Python module that contains the following: When you start the NS using the '-s' switch, it will read your module and call the two functions mentioned above to get your validator objects. Make sure your module is in your Python import path. The NS prints the names of the plugins to show that it's using them and then starts. Have a look at the "NS_sec_plugins" example to see how things are done.

Mobile objects and Code Validators

The mobile code support of Pyro is very powerful but also dangerous, because the server is running code that comes in over the wire. Any code can enter over the wire, correct, buggy, but also evil code (Trojans). It's obvious that loading and running arbitrary code is dangerous. That's why you should set a codeValidator for each Pyro object that might load mobile code (mobile objects). The default validator offers no protection: it accepts all code.

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.

Firewalls

Using a firewall to protect your network has nothing to do with security in Pyro, but it may affect Pyro. Ofcourse the firewall can be used to fully protect your network for systems outside the firewall; it can make it impossible for those systems to connect to your Pyro servers. But if you want to access Pyro objects from outside the firewall, you may have to take some additional steps. Because they have to do with configuring Pyro, and not with security, they are described in detail in the Freatures chapter (topic "DNS, IP addresses and firewalls").

The pickle trojan security problem

Security warning: possible trojan attack

By default, Pyro uses the native Python 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 Gnosis_Utils. To enable this, set the PYRO_XML_PICKLE config item to 1. You need to have said Gnosis_Utils package installed (at least version 1.0.2), 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 Gnosis_Utils package is installed on both ends of the communitcation. 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.

SSL (secure socket layer) support

Pyro supports communication over secure sockets (SSL). Because Python doesn't support server-side SSL out-of-the-box, you'll need the following add-on libraries to enable SSL support: Why M2Crypto? Because it works for both client and server applications, and is thread safe. Note: M2Crypto needs support for RC5 and IDEA compiled into OPENSSL. Since they're copyrighted these options are normally not included in most major OpenSSL ditributions. You might have to recompile OpenSSL from the sources yourself. Beware that if you use this to upgrade to a new OpenSSL version you also have to recompile OpenSSH since it does a version check on the OpenSSL library.

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