Authentication and Database Support (fcdb)

The Freeciv21 server allows for the authentication of users, although by default it is not configured, and anyone can connect with any username.

In order to support authentication, the Freeciv21 server needs access to a database backend in which to store the credentials. To support different database backends, the database access code is written in Lua using luasql. In principle, luasql supports SQLite3, MySQL, and Postgres backends. However, the Freeciv21 server is only built with SQLite3 and the provided database.lua is also only programmed to support SQLite3.

As well as storing and retrieving usernames and passwords, the supplied database access script logs the time and IP address of each attempted login, although this information is not used by the Freeciv21 server itself.

To use the Freeciv21 database and authentication, the server must be installed properly, as it searches for database.lua in the $HOME/.config/freeciv21 directory. The server cannot simply be run from a build directory if authentication is required.

Quick Setup: SQLite

The simplest setup is to use the SQLite3 backend, and this is probably the best option for new deployments. In this setup, the authentication data is stored in a simple file accessed directly by the Freeciv21 server. There is no need for a separate database server process.

To set this up, first create a database configuration file called something like fc_auth.conf, with the database key specifying where the database file is to live. It must be readable and writable by the Freeciv21 server. A good default location is the user’s $HOME directory. Here is an example:

[fcdb]
backend="sqlite"
database="/home/[user]/freeciv21.sqlite"

Note

The username [user] should be changed to a real user.

For more information on the format of this file, see below. There are more settings available, but this file is entirely sufficient for a SQLite3 setup.

Now we need some software and Lua scripts installed on the server to support the SQLite3 database as well as storing passwords with MD5 hashes.

$ sudo apt install luarocks lua5.3 liblua5.3-dev libsqlite3-dev
$ eval $(luarocks path --bin --lua-version 5.3)
$ luarocks --local --lua-version 5.3 install md5
$ luarocks --local --lua-version 5.3 install luasql-sqlite3

Lastly, we need to download the database.lua script file.

$ mkdir -p $HOME/.config/freeciv21
$ cd $HOME/.config/freeciv21
$ wget https://raw.githubusercontent.com/longturn/freeciv21/master/lua/database.lua
$ cd ~

Now start the server with:

$ freeciv21-server --Database ~/fc_auth.conf --auth --Newusers

The first time you do this, you need to create the database file and its tables with the following server command:

/fcdb lua sqlite_createdb()

You should now see a /home/[user]/freeciv21.sqlite file as per the same path given in the fc_auth.conf file.

At this time you are ready to create some users by connecting with the client. Due to the --Newusers flag, when you connect with the client with a previously unknown username, the server will prompt for a password and save the new account to the database.

You may want to prepopulate the users table this way and then restart the server without --Newusers for the actual game, or you can run the game with --Newusers.

Advanced SQLite Usage

SQLite supports working with a temporary database in memory which is never written to disk. To do this, specify database=":memory:" in the configuration file. The database will last only for the lifetime of the freeciv21-server process. Its contents will be lost if the server quits or crashes. It is not saved in the saved game file, either. You will probably need the --Newusers option.

Command-line Options

The following server command-line options are relevant to authentication:

  • -D or --Database <conffile>: Specifies a configuration file describing how to connect to the database. Without this, all authentication will fail.

  • -a or --auth: Enable authentication. Without this, anyone will be able to connect without authentication, and --Database has no effect.

  • -G or --Guests: Allow guests. These are usernames with names starting with “guest”. If enabled, any number of guests may connect without accounts in the database. If a guest name is already in use by a connection, a new guest name is generated. Once connected, guests have the same privileges as any other account. If this option is not specified, accounts are required to connect, and guest account names are forbidden.

  • -N or --Newusers: Allow Freeciv21 clients to create new user accounts through the Freeciv21 protocol. Without this, only accounts which already exist in the database can connect. This might be desirable if you wants users to register via a web front end, for instance.

Lua script database.lua

This script is responsible for checking usernames, fetching passwords, and saving new users (if --Newusers is enabled). It encapsulates access to the database backend, and hence the details of the table layout.

The script lives in lua/database.lua in the source tree. Instructions above place the file into $HOME/.config/freeciv21.

The supplied version supports basic authentication against a SQLite3 database. It supports configuration as shown in the following example:

[fcdb]
backend="sqlite"
host="localhost"
user="Freeciv21"
port="3306"
password="s3krit"
database="Freeciv21"
table_user="auth"
table_log="loginlog"

If that is sufficient for you, it is not necessary to read on. Freeciv21 expects the following lua functions to be defined in database.lua:

  • Try to load data for an existing user.

  • Return TRUE if the user exists, FALSE otherwise in function user_load(conn).

  • Save a new user to the database in function user_save(conn).

  • Log the connection attempt (success is boolean) in function user_log(conn, success).

  • Test and initialise the database connection in function database_init().

  • Free the database connection in function database_free().

Where conn is on object representing the connection to the client which requests access.

The return status of all of these functions should be one of:

fcdb.status.ERROR
fcdb.status.TRUE
fcdb.status.FALSE

indicating an error, a positive result, or a negative result. The following lua functions are provided by Freeciv21:

  • Return the client-specified username in function auth.get_username(conn).

  • Return the client IP address (string) in function auth.get_ipaddr(conn).

  • Tell the server (the MD5 hash of) the correct password to check against.

  • For this connection (usually to be called by function user_load()).

  • Returns whether this succeeded in function auth.set_password(conn, password).

  • Return (the MD5 hash of) the password for this connection (as specified by the client in in function user_save(), or as previously set by the function set_password().

  • The function auth.get_password(conn) runs.

  • Return a value from the --Database configuration file in function fcdb.option(type).

type selects one of the entries in the configuration file by name (for instance the function fcdb.option("backend")).

Freeciv21 also provides some of the same Lua functions that ruleset scripts get: log.*(), _(), etc., but the script is executing in a separate context from ruleset scripts, and does not have access to signals, game data, etc.