.. _server_configuration:

Configuration background information
-------------------------------------

.. note:: This section contains deeper background information about server configuration. If you installed LinOTP via
          the virtual appliance or Debian packages, you probably do not need to read this.

          You only need to read this chapter, if you installed LinOTP manually or want to adapt your LinOTP setup very
          specifically.


LinOTP Server configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. _config_token_database:

Token database
..............

The simple SQLite database may be well used for installations up to 100 tokens. This file based sql database can only
be accessed locally. Being a simple file, it can be easily backed up but it features no additional access settings.
Nevertheless all sensitive data are encrypted with the encKey file. But keep in mind, that this file is located on
the same machine like the SQLite database file. You might have a dedicated database department that is running
databases like Oracle or MS SQL. Please note, that LinOTP make use of the SQLAlchemy framework. You may find the
supported databases here at http://www.sqlalchemy.org/docs/dialects/index.html.

You will then need to change the sqlalchemy.url in your ``linotp.ini`` file, which is usually located at
``/etc/linotp2/linotp.ini``.

For Oracle change it to::

   sqlalchemy.url = oracle://<user>:<password>@<servername>/<database>


Be assured that you set up the encKey before creating the database tables. The database tables are then created by
calling::

   paster setup-app /etc/linotp2/linotp.ini

A more detailed setup description for running LinOTP with Oracle or DB2 can be found at section
:ref:`database_connection`.

.. _python_search_path:

Python search path
..................

The path where your LinOTP components are installed must be contained in your python search path. This will be given,
when you installed LinOTP by either of the described ways.

Anyway if the command ``paster setup-app linotp.ini`` returns the error message::

   pkg_resources.DistributionNotFound: LinOTP

then your python search path needs to be fixed.

Then start a python shell::

   # python
   Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)
   [GCC 4.4.1] on linux2
   Type "help", "copyright", "credits" or "license" for more information.
   >>> import sys
   >>> sys.path
   ['', '/usr/local/lib/python2.6/dist-packages/docutils-0.5-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.5.5-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Pylons-0.9.7-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Tempita-0.4-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/WebTest-1.2-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/WebError-0.10.1-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/WebOb-0.9.6.1-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Mako-0.2.4-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/nose-0.11.1-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/decorator-3.0.0-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/simplejson-2.0.9-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/FormEncode-1.2.2-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/PasteScript-1.7.3-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/PasteDeploy-1.3.3-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Paste-1.7.2-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Beaker-1.4-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/WebHelpers-0.6.4-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Routes-1.10.3-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/Pygments-1.0-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/LinOtpUserIdResolverEE-2.0.1rc3-py2.6.egg',
    '/usr/local/lib/python2.6/dist-packages/LinOTP-2.0.1rc3-py2.6.egg',
    '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk',
    '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload',
    '/usr/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages/PIL',
    '/home/koelbel', '/usr/lib/python2.6/dist-packages/gst-0.10',
    '/usr/lib/pymodules/python2.6', '/usr/lib/python2.6/dist-packages/gtk-2.0',
    '/usr/lib/pymodules/python2.6/gtk-2.0',
    '/usr/lib/python2.6/dist-packages/wx383  2.6-gtk2-unicode',
    '/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode',
    '/usr/local/lib/python2.6/dist-packages']

Check the output for your path. If it is not contained, you need to append your directory to the search path.

Press *Ctrl-D* to exit the python shell.

To append a new path to the Python search path, you need to place a file ``linotp.pth`` into an existing directory of
the python search path. So create a file e.g. ``/usr/lib/python2.6/site-packages/linotp.pth`` with the following
content::

   /usr/local/lib/python2.6/dist-packages/

RADIUS token communication
..........................

Starting with LinOTP 2.4 you can also define RADIUS Tokens, that forward the authentication request to another RADIUS
server. This can be another OTP backend or any other RADIUS server. In the file ``/etc/linotp2/linotp.ini`` you can
define two parameters for this::

   radius.dictfile= /etc/linotp2/dictionary
   radius.nas_identifier = LinOTP

The *radius.dictfile* is the file that contains the RADIUS attributes definitions.
LinOTP comes with a default one. But you can extend it according to special vendor attributes if necessary.
The *radius.nas_identifier* is the NAS_Identifier that is also send within the RADIUS Auth Request.
All other parameters are configured in the RADIUS token itself.

Please see the section :ref:`enroll_radius` for further information on this.

Paster
......
To get a quick result easily you may use the python-paste and just start the paster with the following command::

   paster serve /etc/linotp2/linotp.ini

You should at least enable ``ssl_pem`` in your ``linotp.ini`` to have an encrypted communication between the
authentication module or the management clients and LinOTP. Nevertheless, this will provide you with no authentication
for the management, i.e. everyone having IP access to your LinOTP Server will be able to manage the tokens.

.. note:: *Paster* is also used to create the database tables (see :ref:`config_token_database`)

Start script
''''''''''''

A Red Hat style start script is contained in the packages::

   /ect/init.d/linotp2-paster

This will start the paster as user ``linotp``.

.. note:: In the default configuration the paster would listen on all IP addresses, which means that the LinOTP server
          would be visible without encryption and authentication!

.. note:: When running with Apache, you do not need this start script!

You can start the paster during boot time automatically by issuing the following commands::

   chkconfig --add linotp2-paster
   chkconfig linotp2-paster on


.. _apache_configuration:

Apache web server
.................

To enable encryption and authentication for the LinOTP Server LinOTP can run in a web server. LinOTP will run as WSGI
[#wsgi]_ and thus you can use any web server that supports WSGI. This section describes how to setup your Apache to
serve LinOTP in an encrypted and authenticated manner.

.. [#wsgi] http://code.google.com/p/modwsgi

1. Install apache2,
2. install libapache2-mod-wsgi [#wsgi_debian]_,
3. enable mod-wsgi and mod-ssl with your Apache::

      a2enmod wsgi
      a2enmod ssl

4. If you want to authenticate with username/password do a::

      a2enmod auth_digest

5. With LinOTP an example Apache configuration was installed to  ``/usr/share/doc/linotp/examples/apache2-linotp2``.
   You can copy this file to ``/etc/apache2/sites-available/linotp2``.

6. Activate this configuration by::

      a2ensite linotp2

7. You may disable any other default site::

      a2dissite

.. [#wsgi_debian] This is the Debian package name. Might be different!

In the following section we discuss the Apache configuration file, which you might want to adapt to your needs.

.. _apache_configuration_file:

Apache configuration file
''''''''''''''''''''''''''

This example configuration applies to Apache version 2.4.

The configuration file starts with the VirtualHost definition::

   <VirtualHost _default_:443>
      ServerAdmin webmaster@localhost

Security-relevant HTTP headers are set::

      Header always edit Set-Cookie ^(.*)$ $1;secure
      Header always set X-Frame-Options "DENY"
      Header always set X-XSS-Protection "1; mode=block"
      Header always set Strict-Transport-Security "max-age=315360000; includeSubDomains"
      Header always set X-Content-Type-Options "nosniff"
      Header always set X-Permitted-Cross-Domain-Policies "none"

For security, server access rights are denied globally and only given where necessary::

      <Directory />
         AllowOverride None
         Require all denied
      </Directory>

LinOTP documentation::

      <Directory /usr/share/doc/linotpdoc/html>
         Require all granted
      </Directory>
      Alias /doc/html /usr/share/doc/linotpdoc/html

LinOTP WSGI application link::

      <Directory /etc/linotp2>
         <Files linotpapp.wsgi>
            Require all granted
         </Files>
      </Directory>
      WSGIScriptAlias / /etc/linotp2/linotpapp.wsgi

The *WSGIScriptAlias* binds the ``linotpapp.wsgi`` script to the web server root. You only should change the location
of the ``linotpapp.wsgi`` script, but you should not change the web server root path to something other than ``/``, because all supported LinOTP clients assume that LinOTP can be reached there.

For efficiency, LinOTP will be run in a separate set of WSGI daemon processes rather than as part of Apache itself::

      # The daemon is running as user 'linotp'
      # This user should have access to the encKey database encryption file
      WSGIDaemonProcess linotp processes=1 threads=15 display-name=%{GROUP} user=linotp
      WSGIProcessGroup linotp
      WSGIPassAuthorization On

Note, that the *user=<user>* needs to have write access to the log file specified in linotp.ini
(default ``/var/log/linotp/``) and read access to the ``encKey`` file specified in ``linotp.ini``.

We now set up authentication for the different LinOTP interfaces, based on their URL paths:

**/manage**

   This interface provides the user interface for administrative tasks. All tasks that can be done with the graphical
   management client – except enrolling eToken NG-OTP – can also be done with this web interface. The authentication
   to this web interface needs to be setup in the Apache configuration. You may also setup OTP authentication for the
   management interface. For how to do this see :ref:`otp_apache`.

   The manage application uses the following data interfaces: /system, /license, /audit, and /admin. It is, by default,
   configured in a single LocationMatch directive so that all the interfaces belonging together are secured with the
   same access rights.

**/system**

   This interface is used to configure the LinOTP Server. You should protect this interface either by
   password authentication provided by Apache or by client certificate authentication. The Management Clients (server
   configuration dialog) communicate via this interface. You can restrict access to this interface for a special user
   group, so that several users may manage the tokens but only a few users may configure server settings.

**/license**

   This interface is used to upload license files to the LinOTP server, and to retrieve licensing information. It should
   be protected with authentication similar to that of ``/admin`` or ``/system.``

**/audit**

   This interface is used to search the audit trail to monitor operations. It should be
   protected in the same authentication manner like /admin or /system.

**/admin**

   This is used for all token management tasks like enrolling, assigning, deleting tokens. You should protect this
   interface either by password authentication provided by Apache or by client certificate authentication. The
   Management Clients communicate via this interface.

**/api/helpdesk**

   This interface is used by the linotp-helpdesk web application. It is secured with a different digest auth file than
   the administrative interfaces. If you change the auth type for this interface, be sure to keep the linotp-helpdesk
   auth configuration in sync to ensure seamless interaction between the backend and frontend of the helpdesk.

**/gettoken**

   This interface is used to retrieve OTP values. It is secured with a different digest auth file than the administrative
   interfaces. This means that, by default, no one is allowed to use the interface if no access is explicitly permitted.

**/selfservice**

   This interface is used by end users to manage their own OTP tokens.
   This interface uses the /userservice interface that provides its own authentication, so there is no special need to
   protect it within the Apache configuration. As the user authenticates with a username to this interface, /selfservice
   should only be accessible from your local network.

**/userservice**

   This interface is used by the selfservice application. The user is authenticated against the user database that is
   defined in the corresponding user ID resolver. As the user authenticates with a username to this interface,
   /userservice should only be accessible from your local network but must match the same settings as /selfservice.

**/validate**

   This interface is used to authenticate the users. The authentication modules ``pam_linotp`` and ``rlm_linotp2``
   communicate via this interface. You should encrypt the communication with this interface (running with SSL) and
   you may also setup authentication to this interface, but it is not that crucial as it is with /admin and /system.

   You might want to restrict the IP addresses that are allowed to contact this interface. This can be achieved by a
   configuration like::

      <Location /validate>
         Order deny,allow
         Deny from all
         Allow from 192.168.1.17
      </Location>

The complete default access configuration looks as follows::

      <LocationMatch /(manage|system|license|audit|admin)>
         AuthType Digest
         AuthName "LinOTP2 admin area"
         AuthDigestProvider file
         AuthUserFile /etc/linotp2/admins
         Require valid-user
         #----------------------------------------
         # Here we do client certificate auth
         #----------------------------------------
         # SSLVerifyClient require
         # SSLVerifyDepth  2
         # # Who signed the client certificates
         # SSLCACertificateFile /etc/ssl/certs/ca.crt
         # # what client certs are allowed to log in?
         # SSLRequire ( %{SSL_CLIENT_S_DN_OU} eq "az" and %{SSL_CLIENT_S_DN_CN} in {"linotpadm", "Manfred Mann"} )
      </LocationMatch>

      <Location /api/helpdesk>
         AuthType Digest
         AuthName "LinOTP2 helpdesk area"
         AuthDigestProvider file
         AuthUserFile /etc/linotp2/auth_helpdesk
         Require valid-user
         #----------------------------------------
         # Here we do client certificate auth
         #----------------------------------------
         # SSLVerifyClient require
         # SSLVerifyDepth  2
         # # Who signed the client certificates
         # SSLCACertificateFile /etc/ssl/certs/ca.crt
         # # what client certs are allowed to log in?
         # SSLRequire ( %{SSL_CLIENT_S_DN_OU} eq "az" and %{SSL_CLIENT_S_DN_CN} in {"linotpadm", "Manfred Mann"} )
      </Location>

      <Location /gettoken>
         AuthType Digest
         AuthName "LinOTP2 gettoken"
         AuthDigestProvider file
         AuthUserFile /etc/linotp2/gettoken-api
         Require valid-user
      </Location>

      <LocationMatch /(selfservice|userservice)>
         # The authentication of the selfservice is done from within the application
      </LocationMatch>

      <Location /validate>
         # No Authentication
      </Location>

The  above Location directives demonstrate how to do authentication either with digest authentication or with client
certificate authentication. To create a AuthUserFile for digest authentication you should use the command htdigest.

If you are using client certificate authentication you can restrict access for certain client certificates using the
SSLRequire directive. For a guideline on how to setup SSL and to issue certificates see section :ref:`issuing_ca`::

      ErrorLog /var/log/apache2/error.log
      LogLevel warn

      # Do not use %q! This will reveal all parameters, including setting PINs and Keys!
      # Using SSL_CLIENT_S_DN_CN will show you, which administrator did what task
      LogFormat "%h %l %u %t %>s \"%m %U %H\"  %b \"%{Referer}i\" \"%{User-agent}i\" \
               \"%{SSL_CLIENT_S_DN_CN}x\""" LinOTP2
      CustomLog /var/log/apache2/ssl_access.log LinOTP2

      #   SSL Engine Switch:
      #   Enable/Disable SSL for this virtual host.
      SSLEngine on

      #   If both key and certificate are stored in the same file, only the
      #   SSLCertificateFile directive is needed.
      SSLCertificateFile    /etc/ssl/certs/linotpserver.pem
      SSLCertificateKeyFile /etc/ssl/private/linotpserver.key

Lastly, error responses can be defined. By default, we only configure the code 500 document::

      ErrorDocument 500 "<h1>Internal Server Error</h1> …"

   </VirtualHost>

.. note:: The example uses the SSL certificate linotpserver.pem. If you do not
    have a certificate authority that provides you with a proper certificate, you may
    create a self signed test certificate as described in
    :ref:`creating_ssl_certs`.

Different authentication schemes for Management Interface
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''

There are several different methods to authenticate to the management interface.
All three methods are supported by the WebUI and the command line client.

**Username/Password**

This can be either basic authentication or digest authentication.

.. note:: If you want to authenticate against LDAP (see section :ref:`apache_ldap`), you need to do basic authentication.

You can activate this by::

   a2ensite linotp2

You need to deactivate other schemes by using ``a2dissite``.

**RADIUS Authentication**

You can use the RADIUS authentication to authenticate with OTP tokens to the LinOTP Management.

Activate this by::

   a2ensite linotp2-radius

You need to deactivate other schemes by using ``a2dissite``.

**Client Certificates**

You can also authenticate to the LinOTP management by using client certificates. Please note, that the LinOTP server
then will use the Common Name of the Distinguished Name of the client certificate.

Using the WebUI the client certificate can also be located on a smartcard.

Activate this by::

   a2ensite linotp2-certs

You need to deactivate other schemes by using ``a2dissite``.

.. _apache_ldap:

Authenticating users against LDAP or Active Directory
'''''''''''''''''''''''''''''''''''''''''''''''''''''
You may also want to authenticate to your LinOTP server with already existing accounts in your LDAP or Active Directory.
To accomplish that, you need to configure the corresponding Location directive and do the following steps:

Activate ``authnz_ldap`` for Apache::

   a2enmod authnz_ldap

Configure the Location directive. This could be the /admin, /system and /license controller.
To do this edit the file ``/etc/apache2/sites-enabled/linotp2``::

   <Location /admin>
          AuthBasicProvider ldap
          AuthType Basic
          AuthName "LinOTP 2 admin area"
          AuthLDAPURL "ldap://172.16.200.61:389/ou=linotp,dc=linotp-test,dc=local?sAMAccountName?sub?(objectClass=user)" NONE
          AuthLDAPBindDN "LDAPserviceUser@linotp-test"
          AuthLDAPBindPassword "test123!"
          Require ldap-group cn=linotp_admin_users, ou=linotp, dc=linotp-test, dc=local
  </Location>

In this case all members of the group *linotp_admin_users* are allowed to manage LinOTP and its tokens.
For other possible filters and restrictions see the *authnz_ldap* documentation at http://httpd.apache.org/docs/2.1/mod/mod_authnz_ldap.html .

To activate the changes, restart the Apache web server::

   /etc/init.d/apache2 restart

.. _issuing_ca:

Issuing Certificate Authority
'''''''''''''''''''''''''''''
If you want to setup the Apache web server to run with TLS, you need to have a CA (certificate authority) certificate,
a server certificate, and the private key to the web server certificate.
If you do not have a CA and a web server certificate available, there is also a sample CA contained in the LinOTPdoc
package.

You can find the CA depending on your installation at /usr/share/doc/linotp/examples/CA or
/usr/local/share/doc/linotp/examples/CA.

The sample just consists of two files:

 * Makefile
 * openssl.cnf

Either change to this directory or copy the files to a location you like.

Prior to using the CA, you need to have your distribution packages make and openssl installed.

Typing::

   make

gives you an overview, what you can do with this sample CA. To get started with LinOTP and Apache + SSL you need to do
the following steps:

1. Create your new CA::

     make initca

   This will create a subdirectory keys and it will create the CA certificate. The file ``keys/ca.crt``
   is the CA certificate for the Apache directive  SSLCACertificateFile.

2. Create a request for your web server::

      make req ext=server name=<servername>

3. Sign the request for the web server / issue the certificate for the web server::

      make sign ext=server name=<servername>

   This will create the file ``keys/<servername>.pem`` for the Apache directive  ``SSLCertificateFile`` and the file
   ``keys/<servername>.key`` for the Apache directive  ``SSLCertificateKeyFile``.

4. Create a request for a admin user if you want to use client certificate authentication::

      make req ext=user name=<adminname>

5. Sign the request for the admin user / issue the certificate for the admin user::

      make sign ext=user name=<adminname>

6. The files  ``keys/<adminname>.pem`` and ``keys/<adminname>.key`` need to be transferred to the client and configured
in the LinOTP Management Client GUI.

   .. note:: The private key files created in this process are passphrase protected. If you need to remove the
             passphrase use::

                openssl rsa -in adminname.key -out adminname-wop.key

             which will create a key file adminname-wop.key without a passphrase.

.. note:: linotpadm.py supports key files with passphrases at the command line. glinotpadm.py does not handle
          passphrases nicely at the moment. The request for the passphrase will be echoed to the terminal, where you
          started glinotpadm.py. The passphrase will be requested for every connect to the LinOTP Server, which
          naturally are a lot. Digest authentication and client certificate authentication can not be used at the same
          time.