------------------------
 Security with Red5 0.6
------------------------

:author: Joachim Bauch
:contact: jojo@struktur.de
:Date: $Date: 2007-03-30 00:33:46 +0200 (Fri, 30 Mar 2007) $
:Revision: $Revision: 1798 $
:Id: $Id: HOWTO-Security.txt 1798 2007-03-29 22:33:46Z jbauch $

.. contents::

Preface
==========================
This document describes the Red5 API that was introduced in version 0.6 to
protect access to streams and/or shared objects similar to what the properties
`Client.readAccess` and `Client.writeAccess` provide in the Macromedia Flash
Communication Server / Flash Media Server 2.


Streams
==========================
Read (playback) and write (publishing/recording) access to streams is protected
separately in Red5.


Stream playback security
--------------------------
For applications that want to limit the playback of streams per user or only
want to provide access to streams with a given name, the interface
IStreamPlaybackSecurity_ is available in Red5.

It can be implemented by any object and registered in the ApplicationAdapter_.
An arbitrary number of stream security handlers is supported per application.
If at least one of the handlers denies access to the stream, the client
receives an error `NetStream.Failed` with a `description` field giving a
corresponding error message.

An example handler that only allows access to streams that have a name
starting with `liveStream` is described below::

  import org.red5.server.api.IScope;
  import org.red5.server.api.stream.IStreamPlaybackSecurity;
  
  public class NamePlaybackSecurity implements IStreamPlaybackSecurity {
  
    public boolean isPlaybackAllowed(IScope scope, String name, int start,
      int length, boolean flushPlaylist) {
        if (!name.startswith("liveStream")) {
            return false;
        } else {
            return true;
        }
    };
    
  }

To register this handler in the application, add the following code in the
`appStart` method::

  registerStreamPlaybackSecurity(new NamePlaybackSecurity());

Red5 includes a sample security handler that denies all access to streams
(DenyAllStreamAccess_).


Stream publishing security
--------------------------
In most applications that allow the user to publish and/or record streams,
this access must be limited to prevent the server from being misused.
Therefore, Red5 provides the interface IStreamPublishSecurity_ to deny
publishing of certain streams.

Similar to IStreamPlaybackSecurity_, it can be implemented by any object
and registered in the ApplicationAdapter_. If one of the registered handlers
denies access, the client receives an error `NetStream.Failed` with a
`description` field giving a corresponding error message.

An example handler that only allows authenticated connections to publish a
live stream starting with `liveStream` and deny all other access is described
below::

  import org.red5.server.api.IConnection;
  import org.red5.server.api.IScope;
  import org.red5.server.api.Red5;
  import org.red5.server.api.stream.IStreamPublishSecurity;
  
  public class AuthNamePublishSecurity implements IStreamPublishSecurity {
  
    public isPublishAllowed(IScope scope, String name, String mode) {
        if (!"live".equals(mode)) {
            // Not a live stream
            return false;
        }
    
        IConnection conn = Red5.getConnectionLocal();
        if (!"authenticated".equals(conn.getAttribute("UserType"))) {
            // User was not authenticated
            return false;
        }
        
        if (!name.startswith("liveStream")) {
            return false;
        } else {
            return true;
        }
    };
    
  }

To register this handler in the application, add the following code in the
`appStart` method::

  registerStreamPublishSecurity(new AuthNamePublishSecurity());

Of course, you will also have to add code in one of the `*Connect` or `*Join`
methods that set the `UserType` attribute of a connection to `authenticated`
for users that are allowed to publish streams.

Red5 includes a sample security handler that denies all access to streams
(DenyAllStreamAccess_).


Shared objects
==========================
Once applications get complex, you might want to control the data that is
stored in a shared object, thus not allowing the clients to modify SOs directly
but only through methods exposed by the application.

The interface ISharedObjectSecurity_ can be used to write handlers that deny
certain actions on a given shared object or prevent the client from creating
arbitrary shared objects.

Below is an example handler that only allows the creation of the persistent
shared object `Chat`. Any client may connect to it and only sending messages
`saySomething` through the SO is allowed. All write access to properties is
denied. You could however change properties through serverside code as these
changes are never protected by the security handlers.

::

  import java.util.List;
  import org.red5.server.api.IScope;
  import org.red5.server.api.so.ISharedObject;
  import org.red5.server.api.so.ISharedObjectSecurity;
  
  public class SampleSOSecurityHandler implements ISharedObjectSecurity {
    
    public boolean isConnectionAllowed(ISharedObject so) {
        // Note: we don't check for the name here as only one SO can be
        //       created with this handler.
        return true;
    }
    
    public boolean isCreationAllowed(IScope scope, String name,
      boolean persistent) {
        if (!"Chat".equals(name) || !persistent) {
            return false;
        } else {
            return true;
        }
    }
    
    public boolean isDeleteAllowed(ISharedObject so, String key) {
        return false;
    }
    
    public boolean isSendAllowed(ISharedObject so, String message,
      List arguments) {
        if (!"saySomething".equals(message)) {
            return false;
        } else {
            return true;
        }
    }
    
    public boolean isWriteAllowed(ISharedObject so, String key,
      Object value) {
        return false;
    }
    
  }

To register this handler in the application, add the following code in the
`appStart` method::

  registerSharedObjectSecurity(new SampleSOSecurityHandler());

If you want to register a security handler only for a given shared object,
use code like this::
  
  ISharedObject so = getSharedObject(scope, "MySharedObject");
  so.registerSharedObjectSecurity(new MySOSecurityHandler());


.. _IStreamPlaybackSecurity: http://dl.fancycode.com/red5/api/org/red5/server/api/stream/IStreamPlaybackSecurity.html
.. _ApplicationAdapter: http://dl.fancycode.com/red5/api/org/red5/server/adapter/ApplicationAdapter.html
.. _DenyAllStreamAccess: http://dl.fancycode.com/red5/api/org/red5/server/api/stream/support/DenyAllStreamAccess.html
.. _IStreamPublishSecurity: http://dl.fancycode.com/red5/api/org/red5/server/api/stream/IStreamPublishSecurity.html
.. _ISharedObjectSecurity: http://dl.fancycode.com/red5/api/org/red5/server/api/so/ISharedObjectSecurity.html
