******************************************************************************
INSTALL - Build and Operating instructions for WTimer
******************************************************************************
==============================================================================
Build instructions for the WTimer web application
==============================================================================
The following text describes how to compile and install WTimer. You need a lot
of software to do this, so take some time and patience for this task.
------------------------------------------------------------------------------
Prerequisites for compilation
------------------------------------------------------------------------------
- In general, a UNIX-conforming operating system is required. The UNIX tools
like sed, grep, etc. are needed to build WTimer; furthermore, some parts of
the software rely on the strict and well-known semantics of a UNIX operating
system. (Linux and the BSD variants are counted as UNIX, here.)
- The build system uses the GNU make tool. It is unlikely that other versions
of the make tool work.
- You need Objective Caml [1] version 3.06 or later. The minimal requirement
is the bytecode compiler, the native-code compiler is optional. It is
recommended to enable dynamic loading of shared libraries (if supported on
your platform). You don't need to build the libraries for dbm, graphics, or
tk (which have themselves requirements).
- Once you have Caml, don't forget to add the bin directory to your PATH, so
the compiler can be found.
- Next, you need the findlib library, available on Gerd Stolpmann's site about
Caml [2]. Use the latest version.
- Next, you need Markus Mottl's bindings of Philip Hazel's PCRE library.
Download them here [3]. Of course, you need libpcre first before you can
build the bindings.
- Next, you need the Ocamlnet [4] library. The library parts "netstring" and
"netcgi2" are required. You need version 3 or later (OCamlnet-4 is ok).
- Next, you need PXP, the XML parser for Caml. It is available on Gerd
Stolpmann's site about Caml [5], too. It is sufficient to build the
ISO-8859-1 lexer, you don't need the Unicode support.
- Next, you need WDialog, a web application framework. Get it here [6]. You
need only the library part "wdialog", especially forget all the complicated
things about the Perl bindings, you don't need them. You need version 2.00
(the 2.00-test versions are not sufficient).
- Next, you need Postgresql [7], and Mottl's and Frisch's bindings for it.
Once you have installed all that, you should be able to compile WTimer. See
the installation instructions distributed in the tarballs of the libraries for
details how to build them. Instructions for WTimer can be found below.
------------------------------------------------------------------------------
Other required software
------------------------------------------------------------------------------
Of course, you need a database management system (DBMS) to store the data of
WTimer. The application supports PostgreSQL (prefered) and MySQL
(unmaintained).
I have tested PostgreSQL 7.2 versions, they do. I know that PostgreSQL 7.0 has
too many limitations, so avoid that versions or earlier ones. - MySQL was
version 3.23 in my tests. Ensure that your version has support for
transactions.
Furthermore, you need a web server. If you only want to run WTimer as CGI
program, any web server should do (but I have only tested Apache 1.3).
------------------------------------------------------------------------------
Build configuration
------------------------------------------------------------------------------
There is a configure script in the distribution. Run
./configure -help
to see which options can be selected (which are only very few compared to other
configure scripts). This also shows the defaults.
There are a lot of options regarding the installation directories. The default
layout is:
- -bindir /usr/local/bin: for binaries to be called by non-privileged unix
users. Files: wtimer-admin.
- -sbindir /usr/local/sbin: for binaries to be called by privileged unix users
only. Files: wtimerd.
- -etcdir /usr/local/etc: for configuration files. Files: wtimer-config.xml
- -libdir /usr/local/lib/wtimer: for other binary files that are not usually
called from the command-line. Files: cgi/wtimer.cgi
- -wtimerdir /usr/local/share/wtimer: for other such binary files if they are
platform-independent. This location will contain all the user interface
files (.ui) under the subdirectory "ui", the SQL files creating databases
under the subdirectory "ddl", and the files that must be statically served
by the web server under the subdirectory "static".
The option -prefix changes the common prefix of all these places from
/usr/local to whatever you want.
------------------------------------------------------------------------------
Compile
------------------------------------------------------------------------------
To make the bytecode versions of the programs, run
make all
If you have ocamlopt, the native-code compiler, and if you have built native
versions of all required libraries, you can alternatively run
make opt
to create the native versions of the programs (running much faster).
Note: Do not strip bytecode programs! This does not work. Native-code programs
are stripped by default.
------------------------------------------------------------------------------
Install
------------------------------------------------------------------------------
Now run
make install
to install the programs and the supporting files, in the configured locations.
With
make INST_PREFIX=/path install
you can set an installation prefix, i.e. /usr/local/bin/wtimer-admin would be
installed in /path/usr/local/bin/wtimer-admin. This option is useful to create
binary packages.
There is no script to uninstall wtimer.
==============================================================================
Creation of the wtimer database
==============================================================================
The database is created with the admin tools of the DMBS, i.e. psql or mysql.
The "ddl" directory contains SQL scripts for that purpose.
- Ensure your DBMS is initialized and running
- Create the database under the name "wtimer". For PostgreSQL do "createdb
wtimer", for MySQL do "mysql -e 'create database wtimer'". You might have
to add options to authenticate as database administrator to execute these
commands.
- Copy /usr/local/share/wtimer/ddl/wtimerdb_pg.sql or wtimerdb_my.sql to a
temporary workfile, and adapt the GRANT statements to the needs of your
site. By default, full database access is granted to everybody, this is
usually too much. At minimum, the user running wtimer must be able to
access the database.
- Create the database tables: For PostgreSQL do "psql -f wtimerdb_pg.sql
wtimer", and for MySQL do "mysql wtimer <wtimerdb_my.sql".
At this stage of the installation, the database is empty. The initial
population is done later.
==============================================================================
Configuration of the connection to the DBMS
==============================================================================
The file wtimer-config.xml contains all configuration options as XML entities
of the form
<!ENTITY name "value">
We will now set the database-relevant options after the unixODBC configuration
is done (or checked).
In wtimer-config.xml, set the option "database-name" to the name of the
database (or use "<name>@host" or even "<name>@host:port"). The option
"database-user" is the Unix user as who the application connects to the
database. The option "database-passwd" is the corresponding password (leave
empty if not used, e.g. PostgreSQL usually does not need a password for local
connections).
Now, we can test whether the connection to the DBMS works. Execute
/usr/local/bin/wtimer-admin users
and check the output. This should be a headline only:
USER LOGIN? ADMIN? DESCRIPTION
There are not any user accounts in the database yet. If you get the headline,
the SELECT statement works.
==============================================================================
Creating the administrator account in the database
==============================================================================
It is recommended to create an administrator account by using wtimer-admin.
Most of the other admin tasks can be done from the web interface, so you don't
have to bother with this command any longer.
Simply do
/usr/local/bin/wtimer-admin add-user -login-true -admin-true \
-description "Administrator" -password-stdin admin
to create an account "admin" with administrator privileges. You are asked for
the password. (Of course, the Unix user must have enough rights on the database
to do this operation. This is usually the user configured in wtimer-config.xml,
and it might be necessary that you really become this user.)
WTimer expects that every account has a time sheet with the same name, i.e. the
user "admin" needs a sheet "admin", otherwise login is not possible. To create
this sheet, do
/usr/local/bin/wtimer-admin add-sheet -owner admin \
-description "Administrator's sheet" admin
BTW, you can get a list of all wtimer-admin commands by running
$ /usr/local/bin/wtimer-admin -help
usage: wtimer-admin <command> <options> <arguments>
Available commands:
wtimer-admin dbconfig display database configuration
wtimer-admin users list the users database
wtimer-admin del-user delete user record
wtimer-admin add-user add a user record
wtimer-admin change-user change a user record
wtimer-admin sheets list the sheets
wtimer-admin add-sheet add a sheet
wtimer-admin del-sheet delete a sheet
wtimer-admin export-users export users into XML
wtimer-admin export-sheets export sheets into XML
wtimer-admin export-dataset export users and sheets into XML
wtimer-admin import import an XML file
The commands usually take options and arguments. Use -help to get
more help for an individual command, e.g. wtimer-admin users -help
To see the options of an individual command, call
/usr/local/bin/wtimer-admin command -help
where "command" is replaced by the command you want to know more about.
==============================================================================
Configuration of the web server for CGI
==============================================================================
The following applies to the Apache web server, but as said before, it is
expected that other servers work, too. Of course, the configuration is
syntactically different for them.
You need two URLs for the application. One is the "static URL", to be used for
static files, and the other is the "dynamic URL", for the CGI program. Both can
be totally different. We present here two setups, the first uses a dedicated
"cgi-bin" directory, and the second the same directory for the static and the
dynamic part of the application.
------------------------------------------------------------------------------
CGI setup with cgi-bin directory
------------------------------------------------------------------------------
Here, the dynamic part is located in a cgi-bin directory together with other
CGI programs, and the static part somewhere else. We assume that the cgi-bin
directory is physically at /data/www/cgi-bin, and mounted under the URL
/cgi-bin. The static directory is at /data/www/docs, and mounted under the URL
/. This setup can be achieved by (httpd.conf):
DocumentRoot /data/www/docs
ScriptAlias /cgi-bin/ /data/www/cgi-bin/
<directory /data/www/cgi-bin/>
AllowOverride None
Options ExecCGI FollowSymLinks
Order allow,deny
Allow from all
</directory>
<directory /data/www/docs/>
AllowOverride None
Options FollowSymLinks
Order allow,deny
Allow from all
</directory>
Note that we have turned on that symbolic links are followed; we will use
symlinks, and this option improves even the performance of the web server. The
drawback is that you have to check the whole configuration more carefully.
Now, create the following symlinks:
/data/www/cgi-bin/wtimer.cgi points to /usr/local/lib/wtimer/cgi/wtimer.cgi
/data/www/docs/wtimer-static points to /usr/local/share/wtimer/static
(The latter is a directory.)
Finally, set the option "static-url-prefix" in wtimer-config.xml to the value
"/wtimer-static/".
You can reach the application by typing the URL
"http://host/cgi-bin/wtimer.cgi" into your web browser (replace "host" by the
name of the computer).
------------------------------------------------------------------------------
CGI setup with shared application directory
------------------------------------------------------------------------------
In this scenario, the dynamic part and the static part are located in the same
directory. We assume that this directory is at /data/www/docs, and mounted
under the URL /. This setup can be achieved by
DocumentRoot /data/www/docs
AddHandler cgi-script .cgi
<directory /data/www/docs/>
AllowOverride None
Options ExecCGI FollowSymLinks
Order allow,deny
Allow from all
</directory>
As before, symlinks must be turned on.
Now, create the following symlinks:
/data/www/docs/wtimer.cgi points to /usr/local/lib/wtimer/cgi/wtimer.cgi
/data/www/docs/wtimer-static points to /usr/local/share/wtimer/static
(The latter is a directory.)
Finally, set the option "static-url-prefix" in wtimer-config.xml to the value
"wtimer-static/" (it is relative to the dynamic URL!).
You can reach the application by typing the URL "http://host/wtimer.cgi" into
your web browser (replace "host" by the name of the computer).
------------------------------------------------------------------------------
Variations
------------------------------------------------------------------------------
You can improve the speed of the CGI startup time by compiling the user
interface definition files. Note that also wtimer-config.xml is compiled, so
you have to compile again if you change this file! Run the compiler by
cd /usr/local/share/wtimer/ui
ocamlfind wd-xmlcompiler/wd-xmlcompile wtimer.ui
This creates a file wtimer.ui.bin which can be much faster loaded than all the
.ui and .xml files in this directory. (You need the wd-xmlcompiler which is
part of the wdialog library.)
It is highly recommended to use the native-code compiler ocamlopt to produce
the CGI program. It is much faster than the result of the byte-code compiler.
(However, if speed really matters, choose the AJP connectivity.)
The CGI program recognizes HTTPS requests, so it is not necessary to change the
WTimer configuration for a secure web server.
It is possible to activate the access control facility of the web server, and
to automatically log in as REMOTE_USER without having to type in an additional
password. To do so, set the wtimer-config.xml option "login-dialog" to "no".
The start page of the application does no longer ask for a user name, nor a
password, there is just a "Start" button. If you press that button, the string
"/auth" is appended to the URL (e.g. http://host/wtimer.cgi/auth), and it is
expected that the variable REMOTE_USER contains the name of the WTimer account
to log in as. This account must exist in the WTimer database, but the password
in the database (if any) is not used. Of course, you have to configure the web
server such that the location /wtimer.cgi/auth is protected. In Apache, you can
do
<location /wtimer.cgi/auth>
AuthUserFile /path/to/users-passwd
AuthName "WTimer User Login"
AuthType Basic
Require valid-user
</location>
which forces that the web server asks for a login name and a password, and that
the login name is put into REMOTE_USER. The password is checked against the
local file /path/to/users-passwd. There are other methods, e.g. you can check
against LDAP directories, or you can use X509 certificates (fakeBasicAuth).
==============================================================================
Security considerations
==============================================================================
There are a lot of factors that affect the security of the resulting system. I
think some of these factors are clear, and need not to be mentioned, e.g. the
internet ports of the DBMS and the wtimerd daemon should be secured as much as
possible. However, there are some factors needing more explanations, because
they are specific for the wtimer application, and could be totally different
for a comparable system.
The login page displayed by the application does not encrypt the password, it
is transferred in clear text over the network. Because of this, it is highly
recommended to use SSL for the whole application.
After the login has happened, the web pages contain references to the current
session. These references are only entered into hidden form fields, and are
not stored as cookies, so it is quite difficult to "steal" the session IDs
from the disk of a client system; they are usually not there. The form fields
are only transferred to the server using the POST method, so they can never
occur in log files, nor in the referrer field. Furthermore, the session IDs
contain a verifier that is a checksum of the current state of the session.
Even if you have managed it to steal the session ID, you must still have luck
in order to abuse it, because the state may have changed in the meantime, and
the ID is worthless. Note that it might be possible to steal the session ID
because of so-called cross-site scripting bugs of web browsers.
Another possible way to break in are specially prepared web requests that
trigger errorneous behaviour (e.g. "buffer overflows"). It is not impossible
that WTimer contains such bugs, but it is unlikely, because it is written in a
programming language that is not very "sensitive" to this problem area.
Objective Caml performs array bound checks, does not treat null bytes
specially, and the language incorporates means to catch exceptional behaviour.
It is likely that the application throws an unusual exception for such
requests, and continues operation.
Of course, it is possible that the application logic is implemented in an
errorneous way, leaving the back door unlocked, but I am quite sure that this
is not the case.
==============================================================================
Operating Tasks
==============================================================================
The following sections explain some operating problems you might be interested
in.
------------------------------------------------------------------------------
User management from the command line
------------------------------------------------------------------------------
You can add, delete, and change user accounts from the command-line. Use
wtimer-admin for this task:
- To list the accounts, call
wtimer-admin users
Note that the printed table does not contain the password (it is impossible
to extract the password from the database).
- To add a new user, call
wtimer-admin add-user NAME
where NAME is the name of the user account. There are options to set the
description text, to set the password, and to allow the user to login.
There is also an option to make the user an administrator:
-login-true The user is allowed to login
-login-false The user is not allowed to login (default)
-admin-true The user is an administrator
-admin-false The user is not an administrator (default)
-description <text> Set the description to this text
-password <pw> Set the password to this string
-password-stdin Read the password from stdin
- To change a user account, call
wtimer-admin change-user NAME
where NAME is the name of the user account. The options are the same as for
add-user, so you can selectively set the password without modifying other
attributes of the account.
- To delete a user account, call
wtimer-admin del-user NAME
where NAME is the name of the user account.
------------------------------------------------------------------------------
Export and import
------------------------------------------------------------------------------
You can export the contents of the database as an XML file. This can be useful
to transfer the data to a different system, to migrate to a different type of
DBMS, etc. The exported files can be imported again.
To make an export of the whole contents of the database, call
wtimer-admin export-dataset
which prints the XML data to stdout. There are options to restrict what is
exported:
-user <user> Only export this user (option can be repeatedly given)
-sheet <user> Only export this sheet (option can be repeatedly given)
-start <YYYY-MM-DD> Do not export ealier entries
-end <YYYY-MM-DD> Do not export later entries
By default, all user records, and all sheet records are exported, but the
options -user and -sheet can be used to select a smaller set. -start and -end
specify time bounds.
There are two other export commands: export-users, and export-sheets. These
export only the user records, and only the sheet records, respectively, but
not the other type of data.
All kinds of export files can be imported by:
wtimer-admin import FILE
By default, this command does not overwrite existing records, and stops when
it needs to (the whole transaction is rolled back). It is ok to import a
record that is new, and it is ok to import a record that already exists in the
database if the imported record is identical to the existing version. This is
the "strict mode". You can select another mode by options:
-overwrite Overwrite existing users, sheets, and days
-add Only import new users, sheets, or days; ignore other
-strict Import new users, sheets, or days; fail on overwrite (default)
------------------------------------------------------------------------------
The session table
------------------------------------------------------------------------------
The database contains the dialog sessions in the table "wd_session". The
WTimer application deletes entries that are older than 7 days, so sessions
that are never logged out are removed after a certain period of time. If this
table becomes very large, you can try to enforce a stricter regime by
executing the SQL query
delete from wd_session where last_used < (current_date - interval N days)
regularly (substitute N by the number of days).
--------------------------
[1] see ftp://ftp.inria.fr/lang/caml-light/
[2] see http://download.camlcity.org/download
[3] see http://www.ai.univie.ac.at/~markus/home/ocaml_sources.html
[4] see /projects/ocamlnet.html
[5] see http://download.camlcity.org/download
[6] see /projects/wdialog.html
[7] see http://www.unixodbc.org