mod-sasl module provides user authentication to Turbulence. Inside BEEP, the SASL protocol is used by default to provide user authentication.
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, anconfiguration 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:
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.
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.
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.
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.
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.
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
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.
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.
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..
..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:
#!/usr/bin/python import sys if len(sys.argv) != 3: print "Please provide a password and hashing function: \n Use: " + sys.argv[0] + " [md5|sha1] password" sys.exit (0) # get md5 password if sys.argv[1] == "md5": import md5 value = md5.new (sys.argv[2]).hexdigest ().upper() elif sys.argv[1] == "sha1": import sha value = sha.new (sys.argv[2]).hexdigest ().upper() else: print "ERROR: unsupported hash: " + sys.argv[2] sys.exit (-1) # now we have to insert : every two chars iterator = 2 # hash len is the current length of the hash + every : placed. Because # it is placed every two positions we multiply the length by 1,5 (-1) # to avoid adding : at the end. hash_len = len (value) * 1.5 -1 while iterator < hash_len: value = value[:iterator] + ":" + value[iterator:] iterator += 3 # print the password print "The password prepared is: " + value
To generate passwords do the following:
>> gen-mod-sasl-pass.py md5 YOUR_PASSWORD
Currently, mod-sasl searches for sasl.conf and associated files looking for them in the following other: