This is cfengine-Tutorial.info, produced by makeinfo version 4.0 from
cfengine-Tutorial.texinfo.

INFO-DIR-SECTION System Utilities
START-INFO-DIR-ENTRY
* cfengine Tutorial: (cfengine-Tutorial.info).
                        Cfengine is a language based tool specifically
                        designed for configuring and maintaining BSD
                        and System-5-like operating systems attached
                        to a TCP/IP network.
END-INFO-DIR-ENTRY


File: cfengine-Tutorial.info,  Node: Building flexible time classes,  Next: Scheduling interval,  Prev: Splaying host times,  Up: Using cfengine as a front-end for cron

Building flexible time classes
==============================

   Each time cfengine is run, it reads the system clock and defines the
following classes based on the time and date:

`YrXX::'
     The current year, e.g. `Yr1997', `Yr2001'. This class is probably
     not useful very often, but it might help you to turn on the
     new-year lights, or shine up your systems for the new millenium!

`MONTH::'
     The current month can be used for defining very long term
     variations in the system configuration, e.g. `January',
     `February'. These classes could be used to determine when students
     have their summer vacation, for instance, in order to perform
     extra tidying, or to specially maintain some administrative policy
     for the duration of a conference.

`DAY::'
     The day of the week may be used as a class, e.g. `Monday',
     `Sunday'.

`DayXX::'
     A day in the month (date) may be used to single out by date, e.g.
     the first day of each month defines `Day1', the 21st `Day21' etc.

`HrXX::'
     An hour of the day, in 24-hour clock notation: `Hr00'...`Hr23'.

`MinXX::'
     The precise minute at which cfengine was started: `Min0' ...
     `Min59'.  This is probably not useful alone, but these values may
     be combined to define arbitrary intervals of time.

`MinXX_XX::'
     The five-minute interval in the hour at which cfengine was
     executed, in the form `Min0_5', `Min5_10' .. `Min55_0'.

   Time classes based on the precise minute at which cfengine started
are unlikely to be useful, since it is improbable that you will want to
ask cron to run cfengine every single minute of every day: there would
be no time for anything to complete before it was started again.
Moreover, many things could conspire to delay the precise time at which
cfengine were started. The real purpose in being able to detect the
precise start time is to define composite classes which refer to
arbitrary intervals of time. To do this, we use the `group' or `classes'
action to create an alias for a group of time values.  Here are some
creative examples:


     classes:  # synonym groups:
     
       LunchAndTeaBreaks = ( Hr12 Hr10 Hr15 )
     
       NightShift        = ( Hr22 Hr23 Hr00 Hr01 Hr02 Hr03 Hr04 Hr05 Hr06 )
     
       ConferenceDays    = ( Day26 Day27 Day29 Day30 )
     
       QuarterHours      = ( Min00 Min15 Min30 Min45 )
     
       TimeSlices        = ( Min01 Min02 Min03 Min33 Min34 Min35)

In these examples, the left hand sides of the assignments are
effectively the ORed result of the right hand side. This if any classes
in the parentheses are defined, the left hand side class will become
defined. This provides a flexible and readable way of specifying
intervals of time within a program, without having to use `|' and `.'
operators everywhere.


File: cfengine-Tutorial.info,  Node: Scheduling interval,  Prev: Building flexible time classes,  Up: Using cfengine as a front-end for cron

Choosing a scheduling interval
==============================

   How often should you call your global cron script? There are several
things to think about:

   * How much fine control do you need? Running cron jobs once each
     hour is usually enough for most tasks, but you might need to
     exercise finer control for a few special tasks.

   * Are you going to run the entire cfengine configuration file or a
     special light-weight file?

   * System latency. How long will it take to load, parse and run the
     cfengine script?


   Cfengine has an intelligent locking and timeout policy which should
be sufficient to handle hanging shell commands from previous crons so
that no overlap can take place, *Note Spamming and security::.


File: cfengine-Tutorial.info,  Node: Cfengine network services,  Next: Security and cfengine,  Prev: Using cfengine as a front-end for cron,  Up: Top

Cfengine and network services
*****************************

   This chapter describes how you can set up a cfengine network service
to handle remote file distribution and remote execution of cfengine
without having to open your hosts to possible attack using the `rsh'
protocols.

* Menu:

* What services?::
* How it works::
* Configuring cfd::


File: cfengine-Tutorial.info,  Node: What services?,  Next: How it works,  Prev: Cfengine network services,  Up: Cfengine network services

Cfengine network services
=========================

   By starting the daemon called `cfd', you can set up a line of
communication between hosts, allowing them to exchange files across the
network or execute cfengine remotely on another system.  Cfengine
network services are built around the following components:

`cfengine'
     The configuration engine, whose only contact with the network is
     via remote copy requests. This component does the hard work of
     configuring the system based on rules specified in the file
     `cfengine.conf'. It does not and cannot grant any access to a
     system from the network.

`cfd'
     A daemon which acts as both a file server and a remote-cfengine
     executor. This daemon authenticates requests from the network and
     processes them according to rules specified in `cfd.conf'.  It
     works as a file server and as a mechanism for starting cfengine on
     a local host and piping its output back to the network connection.

`cfrun'
     This is a simple initiation program which can be used to run
     cfengine on a number of remote hosts. It cannot be used to tell
     cfengine what to do, it can only ask cfengine on the remote host
     to run the configuration file it already has. Anyone could be
     allowed to run this program, it does not require any special user
     privileges. A locking mechanism in cfengine prevents its abuse by
     spamming.

`cfwatch'
     This program (which is not a part of the distribution: it is left
     for others to implement) should provide a graphical user interface
     for watching over the configuration of hosts running cfengine and
     logging their output.

With these components you can emulate programs like `rdist' whose job
it is to check and maintain copies of files on client machines.  You
may also decide who has permission to run cfengine and how often it may
be run, without giving away any special user privileges.


File: cfengine-Tutorial.info,  Node: How it works,  Next: Configuring cfd,  Prev: What services?,  Up: Cfengine network services

How it works
============

* Menu:

* Emulating rdist::
* Remote execution of cfengine::
* cfrun::
* Spamming and security::
* cfd protocol::
* Deadlocks and runaway loops::


File: cfengine-Tutorial.info,  Node: Emulating rdist,  Next: Remote execution of cfengine,  Prev: How it works,  Up: How it works

Remote file distribution
------------------------

   This section describes how you can set up `cfd' as a remote file
server which can result in the distrubution of files to client hosts in
a more democratic way than with programs like rdist.

   An important difference between cfengine and other systems has to do
with the way files are distributed.  Cfengine uses a `pull' rather than
a `push' model for distributing network files.  The `rdist' command,
for instance, works by forcing an image of the files on one server
machine onto all clients.  Files get changed when the server wishes it
and the clients have no choice but to live with the consequences.
Cfengine cannot force its will onto other hosts in this way, it can only
signal them and ask them to collect files if they want to. In other
words, cfengine simulates a `push' model by polling each client and
running the local cfengine configuration script giving the host the
chance to `pull' any updated files from the remote server, but leaving
it up to the client machine to decide whether or not it wants to update.

   Also, in contrast to programs like `rdist' which distribute files
over many hosts, cfengine does not require any general `root' access to
a system using the `.rhosts' file or the `/etc/hosts.equiv' file. It is
sufficient to run the daemon as root.  You can not run it by adding it
to the `/etc/inetd.conf' file on your system however.  The restricted
functionality of the daemon protects your system from attempts to
execute general commands as the root user using `rsh'.

   To remotely access files on a server, you add the keywork
`server=HOST' to a copy command. Consider the following example which
illustrates how you might distribute a password file from a masterhost
to some clients.


     copy:
     
       PasswdClients::
     
         /etc/passwd  dest=/etc/passwd owner=root group=0 server=SERVER-HOST

Given that the `cfd' daemon is running on SERVER-HOST, cfengine will
make contact with the daemon and attempt to obtain information about
the file. During this process, cfengine verifies that the system clocks
of the two hosts are reasonably synchronized. If they are not, it will
not permit remote copying.  If cfengine determines that a file needs to
be updated from a remote server it begins copying the remote file to a
new file on the same filesystem as the destination-file. This file has
the suffix `.cfnew'.  Only when the file has been successfully
collected will cfengine make a copy of the old file, (see `repository'
in the Reference manual), and rename the new file into place. This
behaviour is designed to avoid race-conditions which can occur during
network connections and indeed any operations which take some time. If
files were simply copied directly to their new destinations it is
conceivable that a network error could interrupt the transfer leaving a
corrupted file in place.

   Cfengine places a timeout of a few seconds on network connections to
avoid hanging processes.

   Normally the daemon sleeps, waiting for connections from the network.
Such a connection may be initiated by a request for remote files from a
running cfengine program on another host, or it might be initiated by
the program `cfrun' which simply asks the host running the daemon to
run the cfengine program locally.

   _Make sure that you are running cfengine from a shell which has
sensible limits set. The error `too many open files' can occur in long
recursions if you only have a small number of valid descriptors per
shell. It is probably a good idea to set the number of descriptors to
1024._


File: cfengine-Tutorial.info,  Node: Remote execution of cfengine,  Next: cfrun,  Prev: Emulating rdist,  Up: How it works

Remote execution of cfengine
----------------------------

   It is a good idea to execute cfengine by getting `cron' to run it
regularly.  This ensures that cfengine will be run even if you are
unable to log onto a host to run it yourself. Sometimes however you
will want to run cfengine immediately in order to implement a change in
configuration as quickly as possible. It would then be inconvenient to
have to log onto every host in order to do this manually. A better way
would be to issue a simple command which contacted a remote host and
ran cfengine, printing the output on your own screen:


     myhost% cfrun REMOTE-HOST -v
     
      OUTPUT....

A simple user interface is provided to accomplish this. `cfrun' makes a
connection to a remote cfd-daemon and executes cfengine on that system
with the privileges of the cfd-daemon (usually `root'). This has a two
advantages:

   * You avoid having to log in on a remote host in order to reconfigure
     it.

   * Users other than root can run cfengine to fix any problems with
     the system.


   A potential disadvantage with such a system is that malicious users
might be able to run cfengine on remote hosts. The fact that non-root
users can execute cfengine is not a problem in itself, after all the
most malicious thing they would be able to do would be to check the
system configuration and repair any problems.  No one can tell cfengine
what to do using the cfrun program, it is only  possible to run an
existing configuration.  But a more serious concern is that malicious
users might try to run cfengine repeatedly (so-called `spamming') so
that a system became burdened with running cfengine constantly, *Note
Spamming and security::.


File: cfengine-Tutorial.info,  Node: cfrun,  Next: Spamming and security,  Prev: Remote execution of cfengine,  Up: How it works

`cfrun'
-------

   The syntax of the `cfrun' command is


       cfrun -OPTION --LONGOPTION CLASS1 CLASS2 ...

With the exception of the `-d' and `-S' options, all options are passed
on to the remote hosts and are ignored locally. The `-q' option is
always assumed when executing cfengine remotely, so that SplayTime is
effectively zero when polling hosts serially.  If an option includes a
name such as `-Dnewclass', there should not be a space between the
option letter and the name string. The remaining options are treated as
classes to be sent to all the hosts on the network.

   Each host evaluates the classes sent by `cfrun' and decides whether
cfengine should be invoked.  Only hosts which belong to the classes
defined on the `cfrun' command line are executed. This allows you to
single out groups of hosts which should execute cfengine, based on the
very classes which you have defined for your configuration.  If no
classes are sent on the command line, then all hosts are run.

   `cfrun' uses a configuration file which is located under the
`CFINPUTS' directory in order to determine which hosts and in which
order it should try to connect. Because cfengine always uses a reliable
TCP protocol for connections, it verifies each connection rather than
simply broadcasting openly. Using this file you can even simulate
broadcasting to hosts outside your subnet.

   This file should contain every host name you ever want to configure
remotely, because you can still select subsets of the file by
specifying classes which the remote host will understand.  If the
remote host is not in one of the classes you specify when you run
`cfrun', then it will simply ignore the request. Conversely, if you do
not place a host in this file, it will never be contacted when you use
the `cfrun' command. The format of the file is as follows


      #
      # Comment ..
      #
      domain=MY.DOMAIN
      access=USER1,USER2
     
      HOSTNAME1 OPTIONS
      HOSTNAME2 OPTIONS
      ...

It is important to add the domain-name to this file.  The options you
specifiy in this file, per host, are added to those you might specify
on the command line when invoking cfengine remotely.  For instance, you
might know of a bug on one host and decide not to perform interface
configuration on that one machine. You would write a line like this:


       funny.domain -i  # problem host

   You could use `cfrun' inside one of your cfengine configuration
files in order to remotely execute cfengine on all of the other network
machines, by setting up a host list. Be careful not to include the name
of the master host in the list. The locks should prevent cfengine from
being run on the masterhost, avoiding an infinite loop. This way you do
not have to rely on cron running on every system. The disadvantage
however is that cfengine has to poll the systems on the network, which
means that cfengine cannot be working in parallel on all hosts. This
could be inefficient in the long run.


File: cfengine-Tutorial.info,  Node: Spamming and security,  Next: cfd protocol,  Prev: cfrun,  Up: How it works

Spamming and security
---------------------

   The term `spamming' refers to the senseless repetition of something
in a malicious way intended to drive someone crazy(1). In the computer
world some malicious users, a bit like `flashers' in the park(2) like
to run around the net a reveal themselves ad nauseum by sending
multiple mail messages or making network connections repeatedly to try
to overload systems and people(3).

   Whenever we open a system to the network, this problem becomes a
concern.  Cfengine is a tool for making peace with networked systems,
not a tool to be manipulated into acts of senseless aggression. The
cfengine daemon does make it possible for anyone to connect and run a
cfengine process however, so clearly some protection is required from
such attacks.

   Cfengine's solution to this problem is a locking mechanism. Rather
than providing user-based control, cfengine uses a time based locking
mechanism which prevents actions from being executed unless a certain
minimum time has elapsed since the last time they were executed.  By
using a lock which is not based on user identity, we protect several
interests in one go:

   * Restricting cfengine access to root would prevent regular users,
     in trouble, from being able to fix problems when the system
     administrator was unavailable. A time-based lock does not prevent
     this kind of freedom.

   * Accidents with cron or shell scripts could start cfengine more
     often than desirable. We also need to protect against such
     accidents.

   * We can prevent malicious attacks regardless of whom they may come
     from.


   Cfengine is controlled by a series of locks which prevent it from
being run too often, and which prevent it from spending too long trying
to do its job. The locks work in such a way that you can start several
cfengine processes simultaneously without them crashing into each
other. Coexisting cfengine processes are also prevented from trying to
do the same thing at the same time (we call this `spamming').  You can
control two things about each kind of action in the action sequence:

   * The minimum time which should have passed since the last time that
     action was executed. It will not be executed again until this
     amount of time has elapsed. (Default time is 0 minutes so that
     users un-aware of this feature will not be confused by it.)

   * The maximum amount of time cfengine should wait for an old
     instantiation of cfengine to finish before killing it and starting
     again. (Default time is 120 minutes.)


You can set these values either globally (for all actions) or for each
action separately. If you set global and local values, the local values
override the global ones. All times are written in units of _minutes_.


        actionsequence
          (
          action.IfElapsedTIME-IN-MINS
          action.ExpireAfterTIME-IN-MINS
          )

or globally,


       control:
     
          IfElapsed   = ( TIME-IN-MINS )
     
          ExpireAfter = ( TIME-IN-MINS )

For example:


      control:
     
        actionsequence =
          (
          files.IfElapsed240.ExpireAfter180
          copy
          tidy
          )
     
        IfElapsed = ( 30 )

   In this example, we treat the files action differently to the others.
For all the other actions, cfengine will only execute the files part of
the program if 30 minutes have elapsed since it was last run. Since no
value is set, the expiry time for actions is 60 minutes, which means
that any cfengine process which is still trying to finish up after 60
minutes will be killed automatically by the next cfengine which gets
started.

   As for the files action: this will only be run if 240 minutes (4
hours) have elapsed since the last run. Similarly, it will not be
killed while processing `files' until after 180 minutes (3 hours) have
passed.

   These locks do not prevent the whole of cfengine from running, only
so-called `atoms'. Several different atoms can be run concurrently by
different cfengines.  Assuming that the time conditions set above allow
you to start cfengine, the locks ensure that atoms will never be
started by two cfengines at the same time, causing contention and
wasting CPU cycles.  Atoms are defined to maximize the security of your
system and to be efficient. If cfengine were to lock each file it
looked at seperately, it would use a large amount of time processing
the locks, so it doesn't do that. Instead, it groups things together
like this:

`copy, editfiles, shellcommands'
     Each separate command has its own lock. This means that several
     such actions can be processed concurrently by several cfengine
     processes. Multiple or recursive copies and edits are treated as a
     single object.

`netconfig, resolve, umount, mailcheck, addmounts, disable, processes'
     All commands of this action-type are locked simultaneously, since
     they can lead to contention.

`mountall, mountinfo, required, checktimezone'
     These are not locked at all.

   Cfengine creates a directory `~/.cfengine' for writing lock files
for ordinary users.

   The option `-K' or `--no-lock' can be used to switch off the locking
checks, but note that when running cfengine remotely via `cfd', this is
not possible.

   ---------- Footnotes ----------

   (1) Recall the `spam' song from Monty Python's flying circus?

   (2) Recall the `spam' song from Monty Python's flying circus?

   (3) Recall the `spam' song ... get the idea?


File: cfengine-Tutorial.info,  Node: cfd protocol,  Next: Deadlocks and runaway loops,  Prev: Spamming and security,  Up: How it works

Some points on the cfd protocol
-------------------------------

   Cfd uses a form for host-based authorization. Each atomic operation,
such as statting, getting files, reading directories etc, requires a new
connection and each connection is verified by a double reverse lookup in
the server's DNS records.  Single stat structures are cached during the
processing of a file.

   MD5 checksums are transferred from client to server to avoid loading
the server.  Even if a user could corrupt the MD5 checksum, he or she
would have to get past access control with TCP wrappers and the worst
that could happen would be to get the right version of the file.  Again
this is in keeping with the idea that users can only harm themselves
and not others with cfengine.


File: cfengine-Tutorial.info,  Node: Deadlocks and runaway loops,  Prev: cfd protocol,  Up: How it works

Deadlocks and runaway loops
---------------------------

   Whenever we allow concurrent processes to share a resource, we open
ourselves up the possibilty of deadlock. This is a situation where two
or more processes are locked in a vicious stalemate from which none can
escape. Another problem is that it might be possible to start an
infinite loop: cfengine starts itself.

   Cfengine protects you from such loops to a large degree. It should
not be possible to make such a loop by accident.  The reason for this
is the locking mechanism which prevents tasks being repeated too often.
If you start a cfengine process which contains a shell-command to start
cfengine again, this shell command will be locked, so it will not be
possible to run it a second time. So while you might be able to start a
second cfengine process, further processes will not be started and you
will simply have wasted a little CPU time. When the first cfengine
returns, the tasks which the second cfengine completed will not be
repeated unless you have set the `IfElapsed' time or the `ExpireAfter'
time to zero.  In general, if you wish to avoid problems like this, you
should not disable the locking mechanism by setting these two times to
zero.

   The possibility of deadlock arises in network connection. Cfengine
will not attempt to use the network to copy a file which can be copied
internally from some machine to itself. It will always replace the
`server=' directive in a copy with `localhost' to avoid unnecessary
network connections.  This prevents one kind of deadlock which could
occur: namely cfrun executes cfengine on host A (cfd on host A is then
blocked until this completes), but the host A configuration file
contains a remote copy from itself to itself.  This remote copy would
then have to wait for cfd to unblock, but this would be impossible
since cfd cannot unblock until it has the file. By avoiding remote
copies to localhost, this possibility is avoided.


File: cfengine-Tutorial.info,  Node: Configuring cfd,  Prev: How it works,  Up: Cfengine network services

Configuring `cfd'
=================

* Menu:

* Installation of cfd::
* Configuration file cfd.conf::
* TCP wrappers::


File: cfengine-Tutorial.info,  Node: Installation of cfd,  Next: Configuration file cfd.conf,  Prev: Configuring cfd,  Up: Configuring cfd

Installation of `cfd'
---------------------

   To install the cfengine daemon component, you will need to register a
port for cfengine by adding the following line to the system file
`/etc/services file'

        cfengine        5308/tcp

You could do this for all hosts by adding the following to your
cfengine configuration

     editfiles:
     
       { /etc/services
     
        AppendIfNoSuchLine "cfengine        5308/tcp"
       }

To start cfengine at boot time, you need to place a line of the
following type in your system startup files:


     # Start cfengine server
     cfd

Note that `cfd' will reread its configuration file whenever it detects
that it has been changed, so you should not have to restart the daemon,
not send it the HUP signal as with other daemons.


File: cfengine-Tutorial.info,  Node: Configuration file cfd.conf,  Next: TCP wrappers,  Prev: Installation of cfd,  Up: Configuring cfd

Configuration file `cfd.conf'
-----------------------------

   The server daemon is controlled by a file called `cfd.conf'.  The
syntax of this configuration file is deliberately modelled on
cfengine's own configuration file, but despite the similarities, you
cannot mix the contents of the two files.

   Though they are not compatible, `cfengine.conf' and `cfd.conf' are
similar in several ways:

   * Both files use classes to label entries, so that you may use the
     same configuration file to control all hosts on your network. This
     is a convenience which saves you the trouble of maintaining many
     different files.

   * Both files are searched for using the contents of the variable
     `CFINPUTS'.

   * You can use `groups' and `import' in both files to break up files
     into convenient modules and to import common resources, such as
     lists of groups.


   Note that the classes in the `cfd.conf' file do not tell you the
classes of host which have access to files and directories, but rather
which classes of host pay attention to the access and deny commands when
the file is parsed.

   Host name authentication is not by class or group but by hostname,
like the `/etc/exports' file on most unix systems. The syntax for the
file is as follows:


      control:
     
        CLASSES::
     
            domain = ( DNS-DOMAIN-NAME )
     
            cfrunCommand = ( "SCRIPT/FILENAME" )  # Quoted
     
            AutoExecCommand = ( "CFENGINE-START-SCRIPT" )
     
            AutoExecInterval = ( 60 )
     
            MaxConnections = ( MAXIMUM NUMBER OF FORKED DAEMONS )
     
            ChecksumDatabase = ( FILENAME )
     
            IfElapsed = ( TIME-IN-MINUTES )
     
            DenyBadClocks = ( FALSE )
     
            AllowConnectionsFrom = ( IP NUMBERS )
     
            DenyConnectionsFrom = ( IP NUMBERS )
     
            AllMultipleConnectionsFrom = ( IP NUMBERS )
     
            LogAllConnections = ( FALSE/TRUE )
     
            SkipVerify = ( IP NUMBERS )
     
      groups:
     
        GROUP DEFINITIONS
     
      import:
     
        FILES TO IMPORT
     
      admit: | grant:
     
        CLASSES::
     
           /FILE-OR-DIRECTORY
     
             WILDCARDS/HOSTNAMES
     
      deny:
     
        CLASSES::
     
           /FILE-OR-DIRECTORY
     
             WILDCARDS/HOSTNAMES root=HOSTLIST secure=TRUE/ON


The file consists of a control section and access information.  You may
use the control section to define any variables which you want to use
in the remainder of your file. Two variables are special here, they are
reserved.

`cfrunCommand'
     This string is the command which you would like to be executed
     remotely by the `cfrun' command.

`AutoExecCommand'
     This is the name of a command which you use to execute cfengine
     automatically after the interval specified in `AutoExecInterval'.
     Since the output route is ambiguous for a daemon, you should
     provide a wrapper for cfengine which mails you the output, just as
     you would with cron. This script should not normally produce any
     output itself. Any output will go to syslog.

`AutoExecInterval'
     A number of minutes after which you would like cfengine to be run,
     even if you do not force a run with `cfrun'. This can be used
     instead of, or in addition to cron. If used with cron, take
     precautions to set suitable values for `IfElapsed' so that
     unnecessary overlap is avoided.

`MaxConnections'
     This integer value sets a limit on the maximum number of child
     daemon threads which cfd will `fork' in order to handle remote
     requests. The default value is ten.

`IfElapsed'
     The `IfElapsed' anti-spamming filter is also built into `cfd' so
     that a remote user cannot even get as far as causing cfengine to
     parse its input files (which could be used for spamming in
     itself). The time is in minutes, the default is one hour.

`ChecksumDatabase'
     This is the path and filename to a database which will cache MD5
     checksum values server-side. This optimization is only available
     if you have the Berkeley database library `libdb' on your system.
     If this variable is not defined, no database caching will be used
     and checksum values will be computed directly on request. The
     utility of this solution is a trade-off between the time it takes
     to compute the checksum versus the time for a disk-based lookup.

`DenyBadClocks'
     If this is set to `off', cfd will not deny access to clients whose
     clocks are off by more than one hour. The default is to deny
     access to systems whose clocks differ by more than one hour. This
     can prevent messages of the form `Can't stat' file when remote
     copying.

`AllowConnectionsFrom'
     This variable allows a list of numerical IP masks to be specified,
     which cfd will allow connections from.  If the list is not empty
     and a host whose IP address is not specified attempts to connect
     to the daemon, its connection will be closed immediately.    This
     can be used to prevent hanging connection attacks from malicous
     hosts and other denial of service attacks which would bind thread
     resources.
               control:
          
                AllowConnectionsFrom = ( 128.39.89  192.2.0.10 )

`DenyConnectionsFrom'
     Hosts which are included by the allow-list above can be explicitly
     denied access using this list.
               control:
          
                DenyConnectionsFrom = ( 128.39.89.76 )  # rogue host

`AllowMultipleConnectionsFrom'
     This variable should contain a list of IP wildcards to hosts which
     are allowed simultaneous sessions on the server. Hosts which are
     not in this list are allowed to connect only once, i.e. they must
     terminate and reconnect in order to establish a new session. This
     is to prevent a possible attacker from opening multiple sockets
     and never closing them, resulting in a denial of service attack.
     Hosts IP's can be placed here if they could have overlapping copy
     sessions (e.g. long backup transfers which can run over time).
     This prevents the error message "Multiple connections denied/spam
     shield".

     This replaces the AllowMultipleConnections boolean variable which
     existed in version 1.5.4 (only).

`SkipVerify'
     If connecting hosts use a Network Address Translator in order to
     share an IP address, reverse lookup will fail to give a correct
     verification of host identity.  You can switch off cfd's
     verification of host identity for specific IP addresses or
     patterns using this command. E.g.


          SkipVerify = ( 192.0.0.10  192.0.2.  )

     NOTE!! This is a security risk because it means that cfd implicitly
     trusts the connecting hosts! You should be very careful in using
     Network Address Translators in a secure environment. It is not
     recommended for sites which require a high level of security.

`LogAllConnections'
     If set to true, every successful connection will be logged to
     syslog.  This could be useful for identifying abuses of the
     service, if the server should come under attack, e.g. a denial of
     service attack. The IP address can then be excluded from the
     allowed connections list.

``root=''
     This list specificies the names of hosts which are to have read
     access to files, regardless of the owner of the file. This
     effectively gives root users on connecting hosts privileges to
     non-root owned files on the server, but not vice-versa, similar to
     the NFS root mapping, except that there is no question of a client
     being able to modify files on the server. Caution: cfd trusts the
     DNS service, so be aware that cache poisoning attacks are a
     possible way of bypassing access controls.

``secure=true''
     If this option is set, cfd will only serve the named files if the
     copy access type is `secure', i.e. on an encrypted link. This
     presupposes that cfengine has been compiled with a working DES or
     SSLeay library.

   Following the control section comes a list of files or directories
and hosts which may access these. If permissions are granted to a
directory then all sub directories are automatically granted also. Note
that symbolic links are not checked for, so you may need to
specifically deny access to links if they are plain files, but cfd does
not follow symbolic links and give access to files in other directories.

   Fully qualified hostnames should be given in this file. Do not
forget to define the domain name. Authentication calls the unix function
`gethostbyname()' and so on to identify and verify connecting hosts, so
the names in the file must reflect the type on names returned by this
function. You may use wildcards in names to match, for instance, all
hosts from a particular domain.

   Here is an example file
     #####################################################
     #
     # This is a cfd config file
     #
     #####################################################
     
     groups:
     
       PasswdHost = ( nexus )
     
     #####################################################
     
     control:
     
       #
       # Assuming CFINPUTS is defined
       #
     
       cfrunCommand = ( "/usr/local/bin/cfengine" )
     
       variable = ( /usr/local/publicfiles )
     
     #####################################################
     
     admit:   # Can also call this grant:
     
        PasswdHost::
     
          /etc/passwd
     
             *.iu.hioslo.no
     
         FtpHost::
     
         # An alternative to ftp, grant anyone
     
            /local/ftp/pub
     
              *
     
         any::
     
            $CFINPUTS/cfrun.sh
     
              *.iu.hioslo.no
     
     #####################################################
     
     deny:
     
        /etc/services
     
            borg.iu.hioslo.no
     
       /local/ftp
     
            *.pain-in-the-ass.com

   _NOTE I: cfd is not `rpc.mountd', access control is by filename, not
by device name. Do not assume that files lying in subdirectories are
not open for access simply because they lie on a different device. You
should give the real path name to file and avoid symbolic links._

   NOTE II: access control is per host and per user. User names are
assumed to be common to both hosts. There is an implicit trust
relationship here.  There is no way to verify whether the user on the
remote host is the same user as the user with the same name on the local
host.

   If you still have problems with lack of access, it could be that you
have forgotten to define the domain name for your network, or that you
do not understand the TCP wrappers files `/etc/hosts.access' and
`/etc/hosts.deny'.


File: cfengine-Tutorial.info,  Node: TCP wrappers,  Prev: Configuration file cfd.conf,  Up: Configuring cfd

TCP wrappers
------------

   Cfengine tries to incorporate the TCP wrappers package if you have
it on your system.  If you do, then the files `/etc/hosts.allow' and
`/etc/hosts.deny' allow you to give the cfengine/cfd service an extra
level of protection from `clever' spoofing attempts.


File: cfengine-Tutorial.info,  Node: Security and cfengine,  Next: Variable Index,  Prev: Cfengine network services,  Up: Top

Security and cfengine
*********************

* Menu:

* Hints for implementing security::
* Checksum Databases::
* Whom do you trust?::
* Firewalls::


File: cfengine-Tutorial.info,  Node: Hints for implementing security,  Next: Checksum Databases,  Prev: Security and cfengine,  Up: Security and cfengine

Security hints
==============

   Cfengine is not specifically a tool for implementing high security
solutions for system administration, but it has many features which can
be used to monitor the state of your systems and warn about potential
breaches in security. Here are some suggestions as to how you can be
more security conscious with cfengine's help.

_CERT advisories_
     The CERT coordination centre (Computer Emergency Response Team)
     publishes warnings about known bugs and security risks in computer
     systems which can lead to compromised security. Their
     recommendations often involve disabling certain programs, changing
     permissions to remove setuid root flags and editing configuration
     files. These are things which you can deal with using cfengine.

_disabling binaries_
     When to elect to disable a file, cfengine renames it, moves it to a
     file repository (if you have defined one) and changes the mode of
     the file to read only for its owner. This is sufficient to disable
     binary programs and plain files.

_The setuid log_
     Cfengine is always on the lookout for files which are setuid or
     setgid root.  It doesn't go actively looking for them, but
     whenever you get cfengine to check a file or directory with the
     `files' feature, it will make a note of setuid programs it finds
     there. These are recorded in the file `cfengine.HOST.log' which is
     stored under `/etc/cfengine' or `/var/log/cfengine'.  When new
     setuid programs are discovered, a warning is printed, but only if
     you are _root_. If you ever want a complete list, delete the log
     file and cfengine will think that all of the setuid programs it
     finds are new. The log file is not readable by normal users.

_`ChecksumDatabase'_
     In `files' you can set the option `checksum=md5' which will result
     in the md5 value of the named file being cached in a database for
     future reference. If the file changes in any way this will be
     registered and a security warning will be issued. This gives
     cfengine behaviour like Tripwire.

_Suspicious filenames_
     Whenever cfengine opens a directory and scans through files
     (`files', `tidy', `copy'), it is on the lookout for suspicious
     filenames, i.e. files like `..  .' containing only space and/or
     dots. Such files are never created by sensible people, but are
     often used by hackers to try to hide dangerous programs. Cfengine
     prints warnings about such files. The variable list
     `FileExtensions' may be used to detect concealed directories
     during these searches, if users create directories which look like
     common files.

_Spoofing_
     Spoofing refers to attempts to masquerade as another host when
     sending network transmissions. The `cfd' program attempts to
     unmask such attempts by performing double reverse lookups in the
     name service. This verifies by a trusted server that the socket
     address and the host name are really who they claim to be. If you
     have the TCP wrappers package on your system (libwrap) then cfd
     will attempt to use it to detect other spoofs too, *Note TCP
     wrappers::. If you don't have TCP wrappers, then the only line of
     defense is the double reverse lookup.

_Race conditions in file copying_
     When copying files from a source, it is possible that something
     might go wrong during the operation and leave a corrupt file in
     place. For example, the disk might become full while copying a
     file. This could lead to problems. Cfengine deals with this by
     always copying to a new file on the destination filesystem (prefix
     `.cfnew') and then renaming it into place, only if the transfer
     was successful. This ensures that there is space on the filesystem
     and that nothing went wrong with the network connection or the
     disk during copying.

_`size=' in copy_
     As a further check on copying, cfengine allows you to define
     acceptable limits on the size of files. After all, sometimes
     errors might occur quite independently of anything you are doing
     with cfengine. Perhaps the master password file got emptied
     somehow, or got replaced by a binary, through some silly mistake.
     By checking making an estimate of the expected size of the file
     and adding it to the copy command, you can avoid installing a
     corrupt file and making a localized problem into a global one.

_`useshell=' in shellcommands_
     There are dangers in starting scripts from programs which run with
     root privileges. Normally, shell commands are started by executing
     them with the help of a `/bin/sh -c' command. The trouble with
     this is that it leaves one open to a variety of attacks. One
     example is fooling the shell into starting foreign programs by
     manipulating the `IFS' variable to treat '/' as a separator. You
     can ask cfengine to start programs directly, without involving an
     intermediary shell, by setting the `useshell' variable to false.
     The disadvantage is that you will not be able to use shell
     directives such as `|' and `>' in your commands.

_`warnnonusermail' and `warnnonownermail' in control_
     Some users try to hide files in the mail spool directory since they
     have write access to it. Using the above and their corresponding
     `delete' functions, you can check whether someone has tried to
     place a bogus file in the mail directory. A bogus file is
     identified as being one which either does not belong to a user on
     the system, or which does not have the name of a user on the
     system.

_Using cfengine to restart daemons_
     Always remember that processes which are started by a script or by
     cfengine inherit the environment variables which the parent script
     has, including the timezone, path and umask. If you are unwary,
     you might end up resetting the system clock or permission mask for
     certain services. Be careful.


File: cfengine-Tutorial.info,  Node: Checksum Databases,  Next: Whom do you trust?,  Prev: Hints for implementing security,  Up: Security and cfengine

Checksum Databases
==================

   Cfengine can be used to check for changes in files which only
something as exacting as an MD5 checksum/digest can detect. If you
define a checksum database and activate checksum verification,


     control:
     
       ChecksumDatabase = ( /etc/cfengine/cache.db )
     
     files:
     
        /FILENAME checksum=md5 ....

cfengine will build a Berkeley db database of file checksums and warn
you when files' checksums change. This gives cfengine Tripwire
functionality. It can be used to show up Trojan horse versions of
programs. It should be used sparingly though since database management
and MD5 checksum computation are resource intensive opoerations and
this could add significant time to a cfengine run.

   NOTE! Warnings are usually unecessary. If you are worried about the
integrity of the system then don't bother warning about checksum
mismatches here. Make an md5 `copy' comparison with a read only medium
which has correct versions of the program on it. That way if a binary
is compromised you will not only warn about it but also repair the
damage immediately!

   The control variable `ChecksumUpdates' may be switched to `on' in
order to force cfengine to update its checksum database after warning
of a change.  The default value of this variable is off for cfengine
but on for cfd.  This is because cfd uses a database as a cache, while
cfengine uses it as a security check.


File: cfengine-Tutorial.info,  Node: Whom do you trust?,  Next: Firewalls,  Prev: Checksum Databases,  Up: Security and cfengine

Whom do you trust?
==================

   All the developments of the last few years point to the unpleasant
fact that we need to be extra security conscious on the net.  In order
to have any meaningful discussion about security, you need to determine
who you trust and who you don't trust.  No one from outside your
network can force cfengine to do anything you don't want it to do
(unless root access to your system has been compromised by another
route), but you might decide to collect a file from a remote server
which could sabotage your system a treat. Cfengine does not implement
more exacting security than normal host validation. If you are
collecting files from remote servers, you should make sure that they
come from a machine that you trust, particularly if they are files which
could lead to privileged access to your system. Cfengine places the
responsibility on you. You can make cfengine destroy your system, but
no one else can, so make sure you think about what you are doing.

   For example, it would be an extremely foolish idea to copy a binary
program such as `/bin/ps' from a host you know nothing about.  This
program runs as root. If someone were to replace that version of `ps'
with a trojan horse command, you would have effectively opened your
system to attack.

   In remote copies you are setting up an implicit trust relationship.
First of all you trust integrity of the host you are collecting files
from.  Secondly you trust that they have the same username database with
regard to access control. The root user on the collecting host has the
same rights ro read files as the root user on the server. The same
applies to any matched user name. A non-matched username has the same
rights as _nobody_.

   Cfengine performs no cryptographic coding of messages at present, so
if you are sending sensitive data via cfengine, it should be coded in
advance.


File: cfengine-Tutorial.info,  Node: Firewalls,  Prev: Whom do you trust?,  Up: Security and cfengine

Firewalls
=========

   Cfengine is a useful tool for implementing, monitoring and
maintaining firewalls. You can control what programs are supposed to be
on the firewall and what programs are not supposed to be there. You can
control file permissions, processes and a dozen other things which make
up the configuration of a bastion host. At some point in the future this
space might expand into a discussion about how you set up a bastion
host using cfengine.

