Softpanorama

May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Afick

News Perl-based Integrity Checkers Fcheck (Perl) Viper (Perl) Toby
Nabou Slipwire (Perl)   Humor Etc

afick is more complex tool that has TK interface but at the same time has some bugs. It can be recommended only to sysadmin with above average understanding of Perl.  It should work both in Windows and Unix but in reality works only in Linux  due to complex calls/macros used. Please be skeptical about positive press for afick as it is a complex and capricious beast with most of complexity not related to the core functionality. 

With new threats showing up every day, administrators find it increasingly hard to establish continued trust with their filesystems. Luckily, it's easier than you might think to maintain omniscient control of your filesystem. Through effective use of a filesystem integrity checker, you can keep a watchful eye on every aspect of an important machine's filesystem.

There are several filesystem integrity checker applications, both commercial and open source. I chose to deploy afick, because it is written in Perl, which makes it lightweight and easily portable between different operating systems. Though by nature designed for the command line, afick also has an optional Webmin module and a graphical interface written in perl-Tk.

For this article we will focus on the command-line implementation on a SUSE Enterprise 8.0 server, but what you see here should be applicable to just about any *nix distribution.

Afick can be installed  on Windows with ActivePerl. 

NEWS CONTENTS

Old News ;-)

[Feb 18, 2005] NewsForge Check your filesystems' integrity with afick

With new threats showing up every day, administrators find it increasingly hard to establish continued trust with their filesystems. Luckily, it's easier than you might think to maintain omniscient control of your filesystem. Through effective use of a filesystem integrity checker, you can keep a watchful eye on every aspect of an important machine's filesystem.

There are several filesystem integrity checker applications, both commercial and open source. I chose to deploy afick, because it is written in Perl, which makes it lightweight and easily portable between different operating systems. Though by nature designed for the command line, afick also has an optional Webmin module and a graphical interface written in perl-Tk.

For this article we will focus on the command-line implementation on a SUSE Enterprise 8.0 server, but what you see here should be applicable to just about any *nix distribution.

Installation

You can either download and build afick from the source code, or, if you're using a package-based distribution, you can install from an RPM or Debian binary packages. Let's walk through building it from source. To begin, download and unpack the latest version, navigate to the afick directory, and run the following command:

# perl Makefile.pl

Since you aren't installing the GUI, you can safely ignore any errors about missing perl-Tk modules.

Next, type make install to install the console tool. When your machine finishes copying all the necessary files, afick will be installed on your system. Installation is only half the battle, though. The real fun lies in the configuration and testing phase.

Configuration

Afick begins by creating a database of values representing the current state of your filesystem. When you run it later in update mode, afick compares the current filesystem to the original and notes changes.

The exact attributes of your filesystem that are checked are controlled by a configuration file. Afick provides a default configuration file for both Linux and Windows in the directory where it was originally unpacked. In our case, we are interested in the file linux.conf. You can modify a wealth of options in this file, but we will focus only on the essentials.

Afick provides multiple ways to check every file and directory on your system, so no one configuration file is going to work for everyone. For instance, I am running PHPNuke on a Web server that includes forums, which are going to change constantly as users post items and change their preferences. I don't want those changes dumped into my mailbox every day, possibly burying something important. Someone else with a static Web site, however, might want to see that that content is never changed unexpectedly, and would therefore closely monitor that directory. It takes a bit of trial and error to fine-tune afick (or any other integrity checker for that matter) for your specific needs.

Let's begin by initializing the database with the command:

# afick -c /[path_to_linux.conf]/linux.conf -i

The -c tells afick where to find the configuration file it should use, while the -i instructs it to make an initial copy of the filesystem database. This process will take a few minutes. Once it has finished, let your server run for a while, then compare the databases with this slightly different command:

# afick -c /[path_to_linux.conf]/linux.conf -k

The -k argument tells afick to compare the current filesystem against the database specified in the first line of the linux.conf file, which is the initial database. Any changes will be noted on stdout.

Repeat this process a few times until you're getting a feel for what is changing and how so. For instance, if you've got busy log files somewhere outside of /var, they might produce a bundle of changes every time you run afick, which will create white noise around potentially useful data. After you've got a list of repeat offenders, you can tune the linux.conf file.

The linux.conf file actually has a decent description of all the file attributes you can monitor, including device, inode, permissions, owner, last time modified, and several others. You can even create your own rule sets for certain types of files and directories. For instance, you don't want afick reporting warnings about the individual files in /var/log being modified, as these files are going to be modified almost constantly on some systems. To create a rule set that would check the user and group ownership, the device they reside on, and the permissions, you would first add:

#alias
specialrule = u+g+d+p

Then, to apply this custom rule to the /var/log directory, you would add the following line to the =/Dir section of the conf file:

/var/log specialrule

If you want to define a rule set that ignores the /tmp directory, checks only the files ending in .backup in /root, and ignores all files in /home/user that end in .old, you would add the following lines to the alias section of the config file.

!/tmp
/root/*.backup special_rule
exclude_re := /home/user/.*\.old

Afick recognizes the standard Unix wild cards and regular expressions in rule sets. With a little bit of tweaking, you can tune afick to completely monitor your filesystem in all the necessary places, while ignoring the spots that would generate useless noise.

After you've spent some time tweaking your configuration file you need to ensure that afick itself cannot be modified. The most secure way to accomplish this is to put the database, found by default at /var/lib/afick/afick.pag, somewhere that is write-only. Unfortunately a diskette isn't an option because of the size of the afick database; my database is roughly 15MB for a 4GB server. I recommend using an Iomega Zip disk for a couple reasons. Primarily, you can switch a Zip disk from read-only to read-write with the flip of a switch. This is convenient because every time you make a change to your filesystem you'll need to update the database to clear the warnings that afick will produce every time it runs thereafter, which could lead to wasting a lot of CDs if you tried to deploy the database on a CD-R.

No matter where you store your database, you still need to tell the configuration file where to find it. Mount your Zip drive (or your CD) and copy /var/lib/afick/afick.pag to your mount point. Then change the entry for the database location in the first section of the config file to represent the path to your removable media.

database=/mnt/zip/afick

In addition to storing the database on read-only media, I also choose to err on the side of paranoia, and I keep my config file on read-only media as well. In this case, it's a diskette that I've write-protected. This doesn't prevent afick from being run with a separate config file created locally on the server, but it does allow me to be sure that no small detail within the file can be changed without someone physically touching my servers.

Automating it

The final step in configuring afick is automating it. (Note that this is not strictly necessary if you wish to run afick only after certain tasks.) The easiest way to automate afick is with the afick.cron script included in the original directory where you unpacked the source code. If you installed via an RPM, then afick.cron was implemented upon your installation, and should be emailing root as changes occur. If you followed the instructions here and installed from source, you have to add it manually. At your command prompt, just type:

crontab -e
0*/2 * * * root /[path_to_afick.cron]/afick.cron

Then save and exit the editor. This tells your operating system to run afick once every two hours and mail the results, if any, to root.

Updating it

Every time you make a change to a filesystem, you'll want to update the afick database. Unfortunately, this is a point where security can begin to become an inconvenience. You must physically be at the server to change the Zip disk to read-write mode so the database can be updated.

To initiate update mode, simply replace the -k in the afick command line with -u. This will update the database to include any changes that have happened since the last time afick was run. Since afick will continue using the new database to ensure file integrity, you should always run afick once in compare mode before updating it, to be sure that the database you are about to create won't report recently compromised system commands or files as legitimate. As a further level of protection, afick has built-in integrity checks it performs on its own executables to ensure that afick itself hasn't been modified.

On a short side note, you can also use the update feature of afick to monitor exactly what changes a program's installation procedure makes to a filesystem by using the update feature immediately before and immediately after the installation. This is extremely useful in situations where you cannot verify the authenticity of an application before you install it. Just make sure when you test it with afick that you don't do so on a mission-critical machine. You can also use afick for retroactive testing to ensure uninstalling the software actually returns your filesystem to its previous state.

The future of afick

Afick is a work in progress. In recent conversations, developer Eric Gerbier said he intends to include in future releases a daemon-enabled version that doesn't rely on cron to run afick, thus delivering real-time filesystem monitoring. An option to export afick's results in HTML/XML is in the works for version 3.0, due out sometime in the next few months.

No system will ever be completely safe from malicious users and unauthorized access. If a machine under your control becomes compromised, you must have the proper precautions in place to quickly mitigate the damage and restore services. With a file integrity checker such as afick in place, when that dreaded day comes, you will be prepared to determine exactly what has happened (or is happening) and react accordingly.

In order for afick, or any other file integrity checker, to work as needed, you'll need to take special care in observing the general actions and changes in your filesystem in order to correctly and efficiently craft your configuration rules. Once you've done that, it's just a matter of staying on top of the ever-changing filesystem. Update regularly and update often, so as to catch problems as they begin, and not when it's too late. If you make these practices a regular part of your daily administration routines, you'll be prepared to react efficiently to a breach in security should the need arise.

Brian Warshawsky has built, supported, and administered mission-critical IT infastructure for the United States Naval Research Laboratory, Virginia Commonwealth University, RichmondAir Wireless, and is currently employed by Sungard Collegis at Virginia State University.

Another File Integrity Checker 2.15-1

afick is another file integrity checker, designed to be fast and fully portable between Unix and Windows platforms. It works by first creating a database that represents a snapshot of the most essential... parts of your computer system. You can then run the script to discover all modifications made since the snapshot was taken (i.e. files added, changed, or removed). The configuration syntax is very close to that of aide or tripwire, and a graphical interface is provided.

(more)

Changes: Afick will now work on Windows Vista/Seven with uac. Afick_cron now uses boune syntax instead of bash syntax. A bug has been fixed for activeperl 5.10.1.1007. Remaining environment... variables in the configuration file are detected/replaced by the check_config and clean_config options.

(

2005-08-30 Security - Customizing the AFICK File Integrity Checker Customizing the AFICK File Integrity Checker

In this article, we set up AFICK. Let's adapt AFICK to use a particular directory tree and a different database. This way, we can fingerprint the OS on one run, and fingerprint more dynamic content with a different job. Here is our configuration file:

[root@ids afick]# cat /etc/afickweb.conf
database:=/var/lib/afickweb/afick
history := /var/lib/afickweb/history
archive := /var/lib/afickweb/archive
report_url := stdout
verbose := no
debug := 0
warn_dead_symlinks := no
follow_symlinks := no
allow_overload := no
report_full_newdel := yes
warn_missing_file := yes
running_files := yes
timing := yes
ignore_case := no
max_checksum_size := 10000000
checkrule = p+d+i+n+u+g+s+b+md5+m
/directorytocheck checkrule
[root@ids afick]#

To initialize the database at the new location, we need to use the -c option to specify the different configuration file, and -i to initialize the database at the new location:

[root@ids afick]# afick -c /etc/afickweb.conf -i
# Afick (2.8-2) init at 2005/08/30 07:21:45 with options (/etc/afickweb.conf):
# database:=/var/lib/afickweb/afick
# history:=/var/lib/afickweb/history
# archive:=/var/lib/afickweb/archive
# report_url:=stdout
# report_full_newdel:=1
# warn_missing_file:=1
# running_files:=1
# timing:=1
# max_checksum_size:=10000000
# Hash database created successfully. 12032 files entered.
# #################################################################
# MD5 hash of /var/lib/afickweb/afick => somemd5hash
# user time : 19.05; system time : 5.43; real time : 60
[root@ids afick]#

Update the database:

[root@ids afick]# afick -c /etc/afickweb.conf -u
# Afick (2.8-2) update at 2005/08/30 07:24:43 with options (/etc/afickweb.conf):
# database:=/var/lib/afickweb/afick
# history:=/var/lib/afickweb/history
# archive:=/var/lib/afickweb/archive
# report_url:=stdout
# report_full_newdel:=1
# warn_missing_file:=1
# running_files:=1
# timing:=1
# max_checksum_size:=10000000
# last run on 2005/08/30 07:21:45 with afick version 2.8-2
new file : /var/lib/afickweb/afick.ctr
new file : /var/lib/afickweb/afick.dir
new file : /var/lib/afickweb/afick.pag
changed file : /directorytocheck/picture.jpg
changed file : /directorytocheck/picture9.jpg
# detailed changes
new file : /var/lib/afickweb/afick.ctr
inode_date   : Tue Aug 30 07:22:45 2005
new file : /var/lib/afickweb/afick.dir
inode_date   : Tue Aug 30 07:24:43 2005
new file : /var/lib/afickweb/afick.pag
inode_date   : Tue Aug 30 07:25:39 2005
changed file : /directorytocheck/picture.jpg
md5          : somemd5hash somemd5hash
filesize     : 2772 2756
mtime        : Tue Aug 30 07:18:37 2005     Tue Aug 30 07:23:41 2005
changed file : /directorytocheck/picture9.jpg
md5          : somemd5hash somemd5hash
filesize     : 2753 2756
mtime        : Tue Aug 30 06:33:06 2005     Tue Aug 30 07:23:42 2005
# Hash database updated successfully : 12035 files scanned, 5 changed 
(new : 3; delete : 0; changed : 2; dangling : 0; exclude_suffix : 0; 
exclude_prefix : 0; exclude_re : 0; degraded : 2)
# #################################################################
# MD5 hash of /var/lib/afickweb/afick => somemd5hash 
# user time : 21.03; system time : 4.91; real time : 56
[root@ids afick]# 

Let's check in the new location:

[root@ids afick]# afick -c /etc/afickweb.conf -k
# Afick (2.8-2) compare at 2005/08/30 07:26:15 with options (/etc/afickweb.conf):
# database:=/var/lib/afickweb/afick
# history:=/var/lib/afickweb/history
# archive:=/var/lib/afickweb/archive
# report_url:=stdout
# report_full_newdel:=1
# warn_missing_file:=1
# running_files:=1
# timing:=1
# max_checksum_size:=10000000
# last run on 2005/08/30 07:24:43 with afick version 2.8-2
# Hash database : 12035 files scanned, 0 changed (new : 0; delete : 0; 
changed : 0; dangling : 0; exclude_suffix : 0; exclude_prefix : 0; 
exclude_re : 0; degraded : 2)
# #################################################################
# MD5 hash of /var/lib/afickweb/afick => somemd5hash 
# user time : 21.28; system time : 4.65; real time : 58
[root@ids afick]#

Now, what we want to do is move the AFICK database to a non-root home directory. The intention is that individual users can run integrity checks on their own files. We need to move the database from /var/lib to /home/limited:

[root@ids lib]# mv afickweb /home/limited
[root@ids lib]# cd /home/limited
[root@ids limited]# ls -l
drwxr-xr-x    3 root     root         4096 Aug 30 07:22 afickweb

Change the permisssions:

[root@ids limited]# chown limited afickweb -R
[root@ids limited]# chmod 700 afickweb -R
[root@ids limited]# ls -l afickweb
total 3048
-rwx------    1 limited   root          471 Aug 30 07:32 afick.ctr
-rwx------    1 limited   root         4096 Aug 30 07:22 afick.dir
-rwx------    1 limited   root      8370176 Aug 30 07:32 afick.pag
drwx------    2 limited   root         4096 Aug 30 07:34 archive
-rwx------    1 limited   root         1138 Aug 30 07:35 history

The configuration file needs to be changed for the new location and moved:

[root@ids limited]# vi /etc/afickweb.conf
[root@ids limited]# mv /etc/afickweb.conf /home/limited/
[root@ids limited]# chmod 700 /home/limited/afickweb.conf
[root@ids limited]# chown limited /home/limited/afickweb.conf
[root@ids limited]# ls -l /home/limited/afickweb.conf
-rwx------    1 limited   root    425 Aug 30 07:37 /home/limited/afickweb.conf
[root@ids limited]#

Update the database:

ids limited $ afick -c ~/afickweb.conf -u
WARNING: (control) directives change : database:=/var/lib/afickweb/afick 
/ database:=/home/limited/afickweb/afick
WARNING: (control) directives change : history:=/var/lib/afickweb/history 
/ history:=/home/limited/afickweb/history
WARNING: (control) directives change : archive:=/var/lib/afickweb/archive 
/ archive:=/home/limited/afickweb/archive
WARNING: (control) directives change : report_url:=STDOUT / report_url:=stdout
# Afick (2.8-2) update at 2005/08/30 07:41:02 with options 
(/home/limited/afickweb.conf):
# database:=/home/limited/afickweb/afick
# history:=/home/limited/afickweb/history
# archive:=/home/limited/afickweb/archive
# report_url:=stdout
# report_full_newdel:=1
# warn_missing_file:=1
# running_files:=1
# timing:=1
# max_checksum_size:=10000000
# last run on 2005/08/30 07:31:48 with afick version 2.8-2
new file : /home/limited/afickweb.conf
new file : /home/limited/afickweb/afick.ctr
new file : /home/limited/afickweb/afick.dir
new file : /home/limited/afickweb/afick.pag
deleted file : /etc/afickweb.conf
deleted file : /var/lib/afickweb/afick.ctr
deleted file : /var/lib/afickweb/afick.dir
deleted file : /var/lib/afickweb/afick.pag
changed file : /directorytocheck/picture.jpg
changed file : /directorytocheck/picture1.jpg
changed file : /directorytocheck/picture2.jpg
# detailed changes
new file : /home/limited/afickweb.conf
inode_date   : Tue Aug 30 07:38:38 2005
new file : /home/limited/afickweb/afick.ctr
inode_date   : Tue Aug 30 07:36:51 2005
new file : /home/limited/afickweb/afick.dir
inode_date   : Tue Aug 30 07:41:02 2005
new file : /home/limited/afickweb/afick.pag
inode_date   : Tue Aug 30 07:41:58 2005
deleted file : /etc/afickweb.conf
parent_date  : Tue Aug 30 07:38:09 2005
deleted file : /var/lib/afickweb/afick.ctr
parent_date  : Wed Dec 31 18:00:00 1969
deleted file : /var/lib/afickweb/afick.dir
parent_date  : Wed Dec 31 18:00:00 1969
deleted file : /var/lib/afickweb/afick.pag
parent_date  : Wed Dec 31 18:00:00 1969
changed file : /directorytocheck/picture.jpg
md5          : somemd5hash somemd5hash 
filesize     : 2747 2754
mtime        : Tue Aug 30 07:28:44 2005     Tue Aug 30 07:38:52 2005
changed file : /directorytocheck/picture1.jpg
md5          : somemd5hash somemd5hash
filesize     : 2761 2758
mtime        : Tue Aug 30 06:43:14 2005     Tue Aug 30 07:33:50 2005
changed file : /directorytocheck/picture2.jpg
md5          : somemd5hash somemd5hash
filesize     : 2773 2754
mtime        : Tue Aug 30 06:48:17 2005     Tue Aug 30 07:38:54 2005
# Hash database updated successfully : 12035 files scanned, 11 changed (new : 
4; delete : 4; changed : 3; dangling : 0; exclude_suffix : 0; exclude_prefix : 
0; exclude_re : 0; degraded : 2)
# #################################################################
# MD5 hash of /home/limited/afickweb/afick => somemd5hash 
# user time : 21.15; system time : 4.98; real time : 57
ids limited $

Note that if you rsync the filesystem offsite, you can use the above configuration to check the root filesystem in a secure way, since nobody can mess with your check database.



Etc

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Created: May 16, 1997; Last modified: March 12, 2019