Plasma GitLab Archive
Projects Blog Knowledge

******************************************************************************
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




This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml