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