All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
mod-sasl: SASL support for Turbulence

Index

Introduction

mod-sasl module provides user authentication to Turbulence. Inside BEEP, the SASL protocol is used by default to provide user authentication.

Base configuration

mod-sasl is a module that provides SASL support for turbulence. It includes facilities to configure which SASL profiles can be enabled and the users database to be used.

This module is included in the Turbulence official distribution. To enable it you must make it available at some of the directories that are used by Turbulence to load modules (see 4.1 Turbulence modules configuration). Under most cases this is done as follows:

>> cd /etc/turbulence/mod-enabled
>> ln -s ../mod-available/mod-sasl.xml

Once included the module you must restart Turbulence. Now the mod-sasl is activated you must configure it. This is done by updating sasl.conf file which is usually located at /etc/turbulence/sasl/sasl.conf. Here is an example:

<mod-sasl>
   <!--  db users:

         type: allows to configure the kind of format that is expected
            to be found while reading the attribute
            location. Currently known formats are xml and mysql.

         location: allows to configure the location of the auth
            database. It can use relative paths, starting from the
            location of the current file. This value also points to
            additional backend configuration, for example, like SQL
            strings used by mysql type.

         serverName: essential configuration item. Atention
            required. This attribute allows to configure the SASL
            database to be used according to the serverName. This
            serverName is a fundamental attribute configured at the
            BEEP session.

            This attribute is mainly used to configure different SASL
            users databases with different capabilities (the most
            notable, remote administration).  It is only allowed one
            default SASL database, that is, an  configuration
            without serverName.
             
            From an administrative perspective, serverName is used to
            provide virtual hosting configuration.
        
         format: allows to configure the format used to store and
            retreive keys stored. By default, if nothing is configured
            md5 is used.  Allowed values are: plain, md5 and sha-1 (in
            security order).  It is recomended to either use md5 or
            sha-1.

         remote: allows to configure the remote module configuration
            for that particular entry. If no value is provided, by
            default is to disable remote administration. See module
            documentation to know more about remote administration.
  
         remote-admins: this attribute allows to configure a list of
            users that are allowed to use the remote administration
            protocol. If this attribute is not defined all users will
            be allowed to admin the users database.
       -->
   <!--  xml database backend format  -->
   <auth-db remote-admins="remote-admins.xml" 
            remote="no" 
            format="md5" 
            location="auth-db.xml" 
            type="xml" />
   <!--  mysql database backend format  -->
   <auth-db format="md5" 
            location="auth-db.mysql.xml" 
            type="mysql" />
   <!--  allowed sasl profiles: at this moment we only support
    plain. Patches?  -->
   <method-allowed>
      <method value="plain" />
   </method-allowed>
   <!--  general sasl options applied to all SASL profiles  -->
   <login-options>
      <!--  number of allowed SASL login failures allowed before
      applying the action. This is useful to avoid brute force
      attacks. To disable login failure limit use action="none". 
      Accepted values for "action":
       - none : nothing is done if the limit is reached. 
       - drop : will drop the connection inmediately.
       -->
      <max-allowed-tries action="drop" value="3" />
      <!--  action to take for users with accounts disabled. In the
      case a BEEP session tries to login with a SASL account disabled,
      then the action configured will applied. To disable remove the
      node or place "none".
      Accepted values for "action":
       - none : nothing is done if a failure on a disabled account is found.
       - drop : will drop the connection inmediately.
       -->
      <accounts-disabled action="drop" />
   </login-options>
</mod-sasl>

Previous configuration file example states that there is a default authentication database (no serverName configured), using the md5 format to store passwords (format), storing such user and password using the default xml backend provided by turbulence (type), which is located at the file provided (location).

The two remaining parameters (remote-admins and remote) allows to configure the remote mod-sasl xml-rpc based administration interface and to configure the set of allowed users that could use this interface. See later for more details.

The rest of the file configures the allowed SASL profiles to be used by remote peers. Currently we only support plain. Virtual host configuration for SASL module

Previous example shows how to configure the default backend used for all serverName configurations. Inside BEEP, once a channel is created, it is allowed to configure the serverName parameter asking the server to act using such role. This value can be used to select the proper auth backend configuration.

How the mod-sasl selects the proper auth-db is done as follows:

  1. If the SASL request is being received in a connection which has the serverName parameter configured (either due to a previous channel created or due to the current SASL channel exchange), then it is searched a <auth-db> node with matches the serverName parameter.

  2. If no match is found in the previous search, it is used the first <auth-db> node found without the serverName attribute configured. That is, the <auth-db> node configured without serverName is used as fallback default auth-db for all auth operations.

Using work-dir attribute to set an user defined SASL database

In the case the profile path under which the connection is running have work-dir attribute defined, then mod-sasl will try to load sasl.conf from that work-dir. If not found, system sasl.conf file will be loaded.

The idea is to allow a user with access to a working directory (and a configured profile path poiting to it) to manage its own database.

Command line interface to the mod-sasl: tbc-sasl-conf

If you have a shell account into the turbulence machine, you can use the tbc-sasl-conf tool to update users database (auth-db.xml), rather than editing directly. You can add a user using the following:

>> tbc-sasl-conf --add-user beep-test
I: adding user: beep-test..
Password:
Type again:
I: user beep-test added!

You can use the –serverName option to select the auth-db to be used by the tool.

>> tbc-sasl-conf --add-user beep-test --serverName beep.aspl.es
I: adding user: beep-test..
Password:
Type again:
I: user beep-test added!

Use tbc-sasl-conf –help to get full help.

SASL-RADMIN: xml-rpc interface to manage SASL databases

Starting from Turbulence 0.3.0, it is included a xml-rpc interface that allows full management for all sasl databases installed. This interface is mainly provided as a way to integrate into third party applications the possibility to manage users, passwords, etc for applications developed.

The following are a minimal set of instructions that will serve you as starting point to integrate and use SASL-RADMIN.

  1. First you must locate the idl interface installed in your system. This is the sasl-radmin.idl file. On systems where pkg-config is available you can find it by using the following:

    >> pkg-config --cflags sasl-radmin
    /usr/share/mod-sasl/radmin/sasl-radmin.idl

  2. This idl file includes not only the interface definition but also the code for all services provided. To build the C client interface, so you can perform XML-RPC invocations, you can do:

    >> xml-rpc-gen --out-stub-dir . --only-client --disable-main-file
    --disable-autoconf /usr/share/mod-sasl/radmin/sasl-radmin.idl \encode
    In the case your system has pkg-config, you can do the following:
    \code
    >> xml-rpc-gen --out-stub-dir . --only-client --disable-main-file
    --disable-autoconf `pkg-config --cflags sasl-radmin`
    [ ok ] compiling: /usr/share/mod-sasl/radmin/sasl-radmin.idl..
    [ ok ] detected IDL format definition..
    [ ok ] detected xml-rpc definition: 'sasl-radmin'..
    [ ok ] found enforced resource: sasl-radmin
    [ ok ] registered valued attribute resource='sasl-radmin'..
    [ ok ] service declaration get_users found..
    [ ok ] found additional options for get_users
    [ ok ] found include on body declaration for get_users
    [ ok ] found include on body file: get-users-include.c
    [ EE ] Failed to open file: get-users-include.c
    [ ok ] registered valued attribute resource='sasl-radmin'..
    [ ok ] service declaration operate_sasl_user found..
    [ ok ] found additional options for operate_sasl_user
    [ ok ] found include on body declaration for operate_sasl_user
    [ ok ] found include on body file: operate-sasl-user.c
    [ EE ] Failed to open file: operate-sasl-user.c
    [ ok ] document is well-formed: /usr/share/mod-sasl/radmin/sasl-radmin.idl..
    [ ok ] document is valid: /usr/share/mod-sasl/radmin/sasl-radmin.idl..
    [ ok ] component name: 'sasl-radmin'..
    [ ok ] using '.' as out directory..
    [ ok ] generating client stub at: ...
    [ ok ] creating file: ./sasl_radmin_xml_rpc.h
    [ ok ] creating file: ./sasl_radmin_struct_sasluser_xml_rpc.h
    [ ok ] creating file: ./sasl_radmin_struct_sasluser_xml_rpc.c
    [ ok ] creating file: ./sasl_radmin_array_sasluserarray_xml_rpc.h
    [ ok ] creating file: ./sasl_radmin_array_sasluserarray_xml_rpc.c
    [ ok ] creating file: ./sasl_radmin_types.h
    [ ok ] creating file: ./sasl_radmin_xml_rpc.c
    [ ok ] server stub have been disabled..
    [ ok ] compilation ok

    Don't mind about EE messages about missing files. Those ones are used by the server side component, which is not your case. Along with the output, the command list the set of files installed.

  3. This will build a set of files that must be integrated into your client application according to your building tools. For autoconf users just include that files into your "product_SOURCES" directive. See Vortex xml-rpc-gen tool documentation for more information for an initial explanation.

  4. As a last step, you must activate the remote administration on each domain that will be allowed to do so. This done by using the remote and remote-admins attributes. The first one must be set to "yes". The second must point to a db-list having a list of allowed SASL administrators. See Turbulence Db-List management to setup the administrator list.

Using MySQL to auth SASL accounts

This section assumes you already have installed mod-sasl-mysql either due to source "make install" or because your distribution provides a package to install it. To check it, look if you have a file called extension.modules located at ${sysconfdir}/turbulence/sasl directory. To know your sysconfdir value use:

>> turbulence --conf-location

Inside that file (exension.modules) you should find a declaration like follows:

<extensions>
   <!--  load MySQL backend support for SASL module  -->
   <ext location="/usr/lib/turbulence/modules/mod-sasl-mysql.so" />
</extensions>

To use a MySQL database to auth SASL accounts you must first prepare your MySQL server with some SQL to store those users accounts and prepare your SQL queries to adapt your particular structure. There is no fixed or expected SQL structure, so you can adapt the following example with no problem.

The following is a working example used by Turbulence regression test to check mod-sasl-mysql module. It will work in most situations so you can start with it. Connect to your database and run the following. Rembember to change user and password:

-- create database
CREATE user turbulence_test IDENTIFIED BY '1234';
UPDATE mysql.user SET host = 'localhost' WHERE user = 'turbulence_test' AND host = '%';
CREATE database turbulence_test;
GRANT ALL ON turbulence_test.* TO turbulence_test@localhost;
-- connect to the database
USE turbulence_test
-- Create users database
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY) engine = innodb, charset = utf8;
ALTER TABLE users ADD COLUMN auth_id varchar (255);
ALTER TABLE users ADD COLUMN password varchar (255);
ALTER TABLE users ADD COLUMN is_active int default 1;
ALTER TABLE users ADD COLUMN serverName varchar(255);
-- Insert some test users (user: aspl, password: test)
insert into users (auth_id, password) values ('aspl', '09:8F:6B:CD:46:21:D3:73:CA:DE:4E:83:26:27:B4:F6');

Now you need to enable this database to by used by mod-sasl. This is done by updating your sasl.conf (usually found at /etc/turbulence/sasl/sasl.conf) to have a declaration like follows:

<!-- mysql database backend format -->
<auth-db type="mysql"
location="auth-db.mysql.xml"
format="md5" />

Note that this <auth-db> declaration do not provide a serverName value. This means it will be used for all auth requests if no other especific database is found for the provided serverName and no other default database is found prior this one. In the case you want to use MySQL only for a particular serverName, set it.

Now you have registered this <auth-db> database, mod-sasl will redirect requests to mod-sasl-mysql. Fine, but now you need to tell mod-sasl-mysql how to handle requests. To do so, fill the auth-db.mysql.xml file with the following:

<sasl-auth-db>
   <!--  The following defines the connection settings that will be used to connect the database  -->
   <connection-settings port="" 
                        host="mysql_host" 
                        database="mysql_database" 
                        password="mysql_password" 
                        user="mysql_user" />
   <!--  the following defines the SQL query that will be used to get
       the password associated to a user (auth_id) and under a
       serverName. Here is the list of provided values:

       - %u : the auth_id requested.

       - %n : the serverName associated to the request. If not defined
              it will be empty string. Keep in mind for your SQL.

       - %i : authorization_id

       - %m : SASL method 

       - %p : remote peer ip address.
   -->
   <get-password query="SELECT password FROM users WHERE auth_id = '%u'" />
   <!--  the following defines the optional SQL query that will be used to
        report login ok or login failure according to %t (status)
        which contains "ok" or "failed". The following variables are supported:

       - %t : auth status: "ok" or "failed"

       - %u : the auth_id requested.

       - %n : the serverName associated to the request. If not defined
              it will be empty string. Keep in mind for your SQL.

       - %i : authorization_id

       - %m : SASL method 

       - %p : remote peer ip address.
    -->
   <auth-log query="INSERT INTO auth_log (user, status, ip, serverName) VALUES ('%u', '%t', '%p', '%n')" />
   <!--  the following defines the optional SQL query that will be used
        to ask for the filter IP declaration, along with the
        activation status for this filter. This filter will be used by
        the auth engine to allow or not the auth process. 

	Valid declarations are the following:

          - Just the IP list separated by comas:  "192.168.0.132, 192.168.0.137, 89.140.23,4"
          - A netmask declaration: "89.140.23.0/29, 192.168.0.132/32"

        The SQL sentence must return a tuple where the first parameter
        is a boolean value indicating if there is a filter configured
        and the second parameter the filter itself:
	
        The following variables are supported:

	- %u : the auth_id requested.
	
	- %n : the serverName associated to the request. If not defined
	       it will be empty string. Keep in mind for your SQL.
	
	- %i : authorization_id

        - %m : SASL method 

        Note %p (the remote peer ip address) is not provided. This is
        to enforce that the user space only has to especify the
        filter, not to deal with the filter itself.
 
	 -->
   <ip-filter query="SELECT ip_filter FROM user WHERE name = '%u'" />
</sasl-auth-db>

As you can see the file is self explanatory. There is a declaration to provide connection settings to reach the MySQL server and a declaration with the SQL required to get the password.

Reached this point you are now able to SASL auth your users using a MySQL database. However..

Format and how to create hashed passwords compatible with mod-sasl

..an important detail is how to generate the format used to store the password. In the case use "plain" format (format="plain" attribute declaration inside <auth-db>) then nothing especial is required. In the case you use md5 or sha-1 you must hash the password using the corresponding method, upper case the result, and inverleave a ":" sign each 2 positions. For example:

Plain password: test
MD5: 09:8F:6B:CD:46:21:D3:73:CA:DE:4E:83:26:27:B4:F6
SHA-1: A9:4A:8F:E5:CC:B1:9B:A6:1C:4C:08:73:D3:91:E9:87:98:2F:BB:D3

Along with mod-sasl code is included a python script that can help you generating these passwords and as example of code so your application can generate those passwords too. The application is gen-mod-sasl-pass.py, and its content is:

1 #!/usr/bin/python
2 
3 import sys
4 
5 if len(sys.argv) != 3:
6  print "Please provide a password and hashing function: \n Use: " + sys.argv[0] + " [md5|sha1] password"
7  sys.exit (0)
8 
9 # get md5 password
10 if sys.argv[1] == "md5":
11  import md5
12  value = md5.new (sys.argv[2]).hexdigest ().upper()
13 elif sys.argv[1] == "sha1":
14  import sha
15  value = sha.new (sys.argv[2]).hexdigest ().upper()
16 else:
17  print "ERROR: unsupported hash: " + sys.argv[2]
18  sys.exit (-1)
19 
20 # now we have to insert : every two chars
21 iterator = 2
22 
23 # hash len is the current length of the hash + every : placed. Because
24 # it is placed every two positions we multiply the length by 1,5 (-1)
25 # to avoid adding : at the end.
26 hash_len = len (value) * 1.5 -1
27 while iterator < hash_len:
28  value = value[:iterator] + ":" + value[iterator:]
29  iterator += 3
30 
31 # print the password
32 print "The password prepared is: " + value

To generate passwords do the following:

>> gen-mod-sasl-pass.py md5 YOUR_PASSWORD

Configuring mod-sasl search path

Currently, mod-sasl searches for sasl.conf and associated files looking for them in the following other: