Before using Gate Guardian, please *do* read the security
information in the INSTALL.gateguardian file.  You may also want
to take a look at the TestLog.

--

Gate Guardian is a library of C / C++ code that aims at improving
software security.  It is intended to be used in third party
projects.  At the time of this writing, Gate Guardian provides
functions to shield newly created processes from dangerous
environment settings.  Additional features are planned for the
near future.

Gate Guardian is being developed to improve software security in
many projects.  Much effort is spent in its design to make it
useable by as many people as possible.  This fact reflects in the

Design Guidelines
-----------------

1. Security

   Secure default settings.  If less security is needed, it must
   be requested explicitly by the user.

2. Ease of Use

   Ease of use is very important in software security as security
   is often "added" in a hurry.  ("Adding" security is misleading
   though.  Programs have to be designed for security).
   Therefore, Gate Guardian

    - can be incorporated in a project with minimal effort,
    - should be easy to configure and easy to understand,
    - has secure default settings,
    - uses the BSD license so that everybody can use it with
      almost no restrictions.

3. Portability

   The same code has to work on a wide range of UNIX systems
   (POSIX and non-POSIX) in C and C++ programs without
   modifications.

FEATURES
========

gateguardian.c

Routines to be called right at the beginning of a process.

 * Disable core dumps.
 * Set a safe umask (077 by default).
 * Clean up signal handlers.
 * Clean up or filter dangerous environment variables.
 * Close open file descriptors
 * Make sure stdin, stdout and stderr are sane.
 * Set the working directory.
 * Change or drop privileges.
 * Put process in a chroot() jail.

fileguardian.c

 * Functions to determine whether a given directory is safe for
   creating private files.
 * Functions to create temporary files in a safe location.
 * A function to remove unnecessary characters from a path,
   e.g. "///" -> "/".
 * Functions to check whether a given path is absolute or
   relative, a plain file name etc.

inputguardian.c

 * Funtions inputg_ato... that parse strings into integer types
   similar atoi, atol etc. do, but with proper error handling.
 * Function to verify email adresses.
 * Functions filter html documents (to prevent cross site
   scripting).

LINKING A PROJECT WITH GATE GUARDIAN
====================================

Gate Guardian supports two approaches to link its code with a
project's sources:  including the .c source file using the C
preprocessor, linking with a static library, and linking with a
shared library.

1. Including the .c source files

To use Gate Guardian in a project, copy the file
src/gateguardian.c to the project's source directory and #include
it from the file with the main() function.  For example, the
project tree might look like this:

  myproject/
    doc/
      ...
    src/
      gateguardian.c
      main.c
    NEWS
    ...

  ---------------------------- main.c ----------------------------
  #include <stdio.h>
  #include "gateguardian.c"

  int main(void)
  {
    /* ... call gateguardian here ... */
    printf("Hello, world!\n");

    return 0;
  }
  ----------------------------------------------------------------

One disadvantage of this approach is that a program has to be
recompiled to upgrade to a later version of Gate Guardian.

2. Linking with libgateguardian

Any program can be linked to the libgateguardian library by adding
the appropriate option to the linker call in the Makefile.
Usually, "-lgateguardian" is appended to the other options of the
linker commands.  The details depend on the project that is to be
modified.  In addition, any source file using a function from the
library should include the appropriate header file:

  #include <gateguardian_headers.h>
  #include <fileguardian_headers.h>
  #include <inputguardian_headers.h>
  ...

or

  #include <gateguardian.h>
  #include <fileguardian.h>
  #include <inputguardian.h>
  ...

The first form is recommended because it includes all necessary
system headers.  In the second form, the programmer has to take
care of that.

Gate Guardian provides both, a shared and a static version of
libgateguardian.

USING GATE GUARDIAN
===================

gateguardian.c
--------------

The next step is to configure Gate Guardian to your needs.  The
file gateguardian.c provides a configuration structure of type
gateg_cfg_t.  First, the gateg_init_cfg() function initializes the
structure with default values.  The user can then modify the
defaults.  Finally, the gateg_safe_init() function does the
necessary work:

  ---------------------------- main.c ----------------------------
  #include <stdio.h>
  #include <stdlib.h>
  #include "gateguardian.c"

  int main(void)
  {
    int rc;
    gateg_cfg_t gg_cfg;

    gateg_init_cfg(&gg_cfg, GATEG_INIT_DFLT);
    /* ... make your changes here ... */
    rc = gateg_safe_init(&gg_cfg);
    if (rc != 0)
    {
      abort();
    }
    printf("Hello, world!\n");


    return 0;
  }
  ----------------------------------------------------------------

The second argument to the gateg_init_cfg() function can be:

  GATEG_INIT_DFLT          :  default settings
  GATEG_INIT_DFLT_PARANOID :  paranoid default settings
  GATEG_INIT_NOP           :  configure manually (do nothing)

(see below).  If anything goes wrong, gateguardian.c calls abort()
to terminate the process.  For security reasons it does not print
a message anywhere.  (For debugging it is a good idea to leave
core dumps enabled by adding the line

  #define GATEG_DEBUG

before

  #include <gateguardian.c>


Customization

The behaviour of gateguardian.c can be controlled through the
gateg_cfg_t structure.  It has a sub-structure ops with a mode
of operation for each feature, and a couple of feature-specific
arguments.  There are five basic modes of operation:

  GATEG_OP_DFLT          :  use the built-in default
  GATEG_OP_DFLT_PARANOID :  use the built-in paranoid default
  GATEG_OP_SET           :  user specified setting
  GATEG_OP_SET_PARANOID  :  paranoid user specified setting
  GATEG_OP_NOP           :  do nothing

The _PARANOID modes work the same as the non-paranoid ones, but
are more strict in some aspects.  The gateg_init_cfg() function
initializes the mode variables to _DFLT, _DFLT_PARANOID or _KEEP
depending of its second argument.

All this may sound complicated, but it isn't.  For example to
change the default working directory, type

  gg_cfg.ops.cwd_set = GATEG_OP_SET;
  gg_cfg.cwd = "/home/foobar/tmp";
  gg_cfg.ops.priv_set = GATEG_OP_NOP;
  gg_cfg.ops.priv_drop = GATEG_OP_NOP;

In addition, the individual operations can be delayed to a later
call of the gateg_safe_init() function by 1 to 15 invocations:

  GATEG_OP_<mode> | GATEG_OP_DELAY_<n>

where <mode> is a mode from the list above and <n> is a number
from 1 to 15.  An operation with a delay of 1 is executed at the
second incovation etc.  If gateg_safe_init() is called even more
often it calls abort().


Return Codes of the gateg_safe_init() Function

There are three possible codes the gateg_safe_init function may
return:

 0  (initialization complete)
    Initialization has been completed.  The gateg_safe_init()
    function may not be called again with the given configuration
    structure.

 1  (initialization incomplete)
    The last step of initialization completed without errors, but
    there are still things to do.  The gateg_safe_init() function
    must be called again later.  This can only occur with delayed
    execution (if any of the GATEG_OP_DELAY_... options is used).

In case of an error, gateg_safe_init calls the abort() function
and never returns.


List of Features

 * Core Dumps

    Disable core dumps (only on platforms that provide the
    setrlimit() function).  This is done first in the
    gateg_safe_init() function, except if GATEG_DEBUG is defined
    when gateguardian.c is included.  In that case core dumps are
    disabled last to aid in debugging with core dumps.

    Default
      Disable core dumps on platforms that support setrlimit(), do
      nothing on other platforms.

    Paranoid
      Call abort() on platforms without setrlimit().

    Customization
      gg_cfg.ops.core_disable:  mode variable

 * Umask

    Set the given umask.

    Default
      Uses the umask 077.

    Paranoid
      Combine the old umask and the new one together by or'ing
      their bits according to the formula "final = (old | new)".
      This ensures that the umask set does not grant more access
      rights on files than the old one.

    Customization
      gg_cfg.ops.umask_set:  mode variable
      gg_cfg.umask        :  the new umask

 * Signal Handlers

    Reset all signal handlers to their default values.

    In a verification step that has to be enabled separately,
    at the end of the gateg_safe_init() function, check if the
    real uid is either 0 or the same as the effective uid.  If
    not, call abort().  Rationale:  another user is able to send
    signals to the process.

    Note:  If the verification step occurs before the first step,
    abort() is called.

    Default
      Reset all signal handlers to their default values in the
      first step.
      Check the real uid as described above in the verification
      step.

    Paranoid
      Nothing special in the first step.
      Nothing special in the verification step.

    Customization
      gg_cfg.ops.sighand_reset :  mode variable
      gg_cfg.ops.sighand_verify:  verification step mode

 * Environment Variables

    Delete, set or filter environment variables.  The user can
    provide a table of variable handlers through
    gg_cfg.evars_handlers to augment the default behaviour:

      gateg_evarhandler_t my_handlers[] = {
        /* handler,
         *...
         */
        GATEG_VAR_END_OF_TABLE
      }

    where handler is one of

      GATEG_VAR_KEEP("var)
        Do not delete the variable var.

      GATEG_VAR_SET("var", "val")
        Set the variable var to the value val.

      GATEG_VAR_DEL("var")
        Delete the variable var.  This can be used to delete
        variables that would be otherwise set by the built-in
        default table.

      GATEG_VAR_REJECT_PATH("var")
        Delete the variavle var if it contains a slash ('/').

      GATEG_VAR_FILTER_LANG("var")
        Delete the variavle var if it contains a slash ('/') or
        percent character ('%').

      GATEG_VAR_FILTER_INT("var")
        Delete the variavle var if it contains anything but
        numbers.

      GATEG_VAR_FILTER_TERM("var")
        Delete the variable if it contains contains any characters
        except letters, digits or -/:+._.

      GATEG_VAR_SET_USER_REAL("var")
        Set the variable to the name of the user (real uid).

      GATEG_VAR_SET_LOGINDIR_REAL("var")
        Set the variable to the path of the user's home directory
        (real uid).

    If there are multiple handlers for one variable (e.g. if the
    custom table specifies a different handler than the built-in
    table), the first handler encountered is used.  If the custom
    table has no entry for a variable, the default table is used
    as described below.

    Example:

      gateg_evarhandler_t my_handlers[] = {
        GATEG_VAR_KEEP("QUERY_STRING"),
        GATEG_VAR_SET("PATH", "/bin:/usr/bin");
        GATEG_VAR_END_OF_TABLE
      }
      /* ... */
      gg_cfg.evars_handlers = my_handlers;

    Default
      Set the variables

        IFS         :  " \t\n"
        PATH        :  _STD_PATH
        USER        :  name of the caller (real uid)
        LOGNAME     :  name of the caller (real uid)
        HOME        :  home directory of the caller (real uid)
        ORIG_USER   :  name of the process owner (effective uid)
        ORIG_LOGNAME:  name of the process owner (effective uid)
        ORIG_HOME   :  home directory of the owner (effectivel uid)

        (_STD_PATH comes from the system include file paths.h).

      Filter the variables

        TERM
          Delete variable if it contains contains any characters
          except letters, digits or -/:+._.

        LANG
        LANGUAGE
        LC_ALL
        LC_CTYPE
        LC_NUMERIC
        LC_TIME
        LC_COLLATE
        LC_MONETARY
        LC_MESSAGES
        LC_PAPER
        LC_NAME
        LC_ADDRESS
        LC_TELEPHONE
        LC_MEASUREMENT
        LC_IDENTIFICATION
          Delete variables if they contain a slash ('/') or
          percent character ('%').

        LINES
        COLUMNS
          Delete variables if they contain anything but numbers.

        TERMCAP
          Delete variables if they contain a slash ('/').

      Delete all other variables.

    Paranoid
      Delete the environment and set only IFS and PATH.

    Customization
      gg_cfg.ops.evars_clean:  mode variable
      gg_cfg.evars_handlers :  customization table

 * Open File Descriptors

    Close all open descriptors except stdin, stdout and stderr.

    Default
      Close all descriptors.

    Paranoid
      Nothing special.

    Customization
      gg_cfg.ops.fds_close:  mode variable

 * Standard Filedescriptors

    Associate stdin, stdout and stderr with /dev/null if any of
    them is not open.

    Default
      Associate descriptor 0 with /dev/null in read mode if it is
      not already open or if it is a directory.  Associate
      descriptors 1 or 2 with /dev/null in write mode if it is not
      already open or if it is a directory.

    Paranoid
      Always close the descriptors and reopen /dev/null.

    Customization
      gg_cfg.ops.fds_std:  mode variable

 * Working Directory

    Set the working directory.  Call abort() if the given path is
    NULL, the empty string, or chdir() fails.

    Default
      Change to root directory (/).

    Paranoid
      Nothing special.

    Customization
      gg_cfg.ops.cwd_set:  mode variable
      gg_cfg.cwd        :  new working directory

 * Managing Privileges

    Set the user id and/or group id of a process so the old value
    can be retrieved, or drop privileges permanently.  Permanently
    drop supplementary groups.  Afterwards, verify that the
    correct uid and gid have been successfully set, and if
    privileges have been dropped, verify that they can not be
    regained.

    Note:  Older systems do not properly support this feature.  It
    should work on POSIX systems and BSD 4.4.  No guarantees can
    be made that it is possible to regain the old privileges after
    a new uid or guid has been set.

    Default
      If the effective uid is 0, drop supplementary groups
      permanently.  Set the real and save uid/gid gid to the
      effective uid/gid, permanently dropping privileges.

    Paranoid
      Nothing special.

    Customization
       gg_cfg.ops.priv_set :  set mode variable
       gg_cfg.ops.priv_drop:  drop mode variable
       gg_cfg.priv_uid:  the uid to use, -1 to keep the old one
       gg_cfg.priv_gid:  the gid to use, -1 to keep the old one

 * Chroot

    Safely call chroot() to switch to the given directory.  Set
    the working directory to the root directory of the chroot()
    environment (this overriddes the directory from the working
    directory feature).

    In a verification step that has to be enabled separately,
    at the end of the gateg_safe_init() function, verify that
    there are no open directories and that the process is not
    running as root int the chroot() environment.  Otherwise call
    abort().

    Note:  If the verification step occurs before the first step,
    abort() is called.

    Default
      The chroot step is disabled.
      The verification step is disabled.

    Paranoid
      Nothing special in chroot step.
      Nothing special in verification step.

    Customization
      gg_cfg.ops.chroot_call  :  mode variable
      gg_cfg.ops.chroot_verify:  verification step mode
      gg_cfg.chroot_dir       :  path of the chroot directory

 * Convenience functions for executing external commands in a safe
   environment.

   * Function:

     int gateg_safe_run_command(char * const argv[])

     This function forks a new process, secures its environment
     with the gateg_safe_init() function and executes the command
     argv[0] with the arguments argv[1], argv[2] ... (up to but
     excluding the first 0 pointer in the array) by calling the
     system function

      execv(argv[0], argv);

     The security settings are the same as when calling
     gateg_init_cfg with the GATEG_INIT_DFLT option except that
     several features are disabled with the GATEG_OP_NOP option:

       ops.chroot_call
       ops.chroot_verify
       ops.priv_set
       ops.priv_drop

     The parent process waits for the chil process to finish
     before it continues to execute.

     The function aborts if an internal call to fork(),
     gateg_safe_init(), execv() or waitpid() fails.

     Returns:

      -1   : The command terminated abnormally without an exit
             status
      other: exit status of the command (0-255)

   * Function:

     int gateg_safe_run_command_with_cfg(
       gateg_cfg_t *cfg, char * const argv[])

     This function works like gateg_safe_run_command().  If cfg
     points to a gateg_cfg_t structure, this is used in the call
     to gateg_safe_init() instead of the default settings provided
     by gateg_safe_run_command().  If cfg is 0, this function is
     equivalent to gateg_safe_run_command().

fileguardian.c
--------------

 * Checking whether files can be created safely in a given
   directory

   A common flaw in many programs is that files are created in
   unsafe locations.  As a consequence, other processes or users
   may read, write or destroy sensitive or vital data or mount
   symlink attacks.  The fileguardian.c library provides functions
   to steer clear of such problems.

   A directory may be considered to be safe for a given user if no
   other user (except root) can write or create files therein or
   in any other directory above it (up to the root directory).

   By default, fileguardian treats any directory as unsafe if it
   has write permission for the group or other users (the
   permissions have one of the bits in 022 set).

   * Function:

     int fileg_check_cwd_safety(void)

     Checks whether the current working directory is safe (see
     above).  If it is safe, 0 is returned, otherwise -1 is
     returned.

     Note: That the directory may no longer be safe once the
     function returns if an attacker is able to mount or remount a
     file system in the path.

   * Function:

     int fileg_check_dir_safety_with_mode(
       const char *name, mode_t mode_forbidden)

     Checks whether the directory <name> is safe (see above).
     <name> may be a relative or an absolute path.  If it is safe,
     0 is returned, otherwise -1 is returned.

     By default (mode_forbidden is 0), directories with write
     permission for the group or others are treated as unsafe.
     More forbidden mode bits can be added through the
     mode_forbidden argument.  For example, with 077 any access to
     the directory by anybody but the process' owner and the root
     user is considered unsafe.

     Always remember to use octal numbers (with a leading zero) or
     the symbolic constants defined for the stat() functionas the
     mode_forbidden argument.

     Note: That the directory may no longer be safe once the
     function returns if an attacker is able to mount or remount a
     file system in the path.

   * Function:

     DIR *fileg_safe_opendir(const char *name)

     Checks whether the directory <name> is safe (see above),
     opens it with the opendir() function.  If it is safe, the DIR
     pointer is returned, otherwise 0 is returned.

     Note: Testing the safety of the path works internally by
     appending "/.." to the name for each directory in the
     path.  Thus, it is impossible to test a path if the resulting
     path is longer than the maximum allowed path length (system
     dependent).

   * Function:

     DIR *fileg_safe_opendir_with_mode(
       const char *name, mode_t mode_forbidden)

     Checks whether the directory <name> is safe (see above),
     opens it with the opendir() function.  If it is safe, the DIR
     pointer is returned, otherwise 0 is returned.  The
     mode_forbidden argument is treated exactly as for the
     fileg_check_dir_safety_with_mode() function.

     Note 1: This function has a possible race condition on
     platforms that do not support the dirfd() function.  It may
     be possible to redirect the directory path to a different
     location (for example by mounting or unmounting a file
     system) after the safety of the path has been checked but
     before the directory is opened.  There is probably no way to
     avoid this problem.

     Note 2: Testing the safety of the path works internally by
     appending "/.." to the name for each directory in the path.
     Thus, it is impossible to test a path if the resulting path
     is longer than the maximum allowed path length (system
     dependent).

 * Creating temporary files safely

   The following allow to create temporary files in any safe
   directory and make sure that no existing file is overwritten.

   * Function:

       FILE *fileg_safe_tmpfile(void)

     Tries to create an anonymous temporary file in the directory
     P_tmpdir (usually defined in stdio.h as "/tmp"), creates it
     for reading and writing and returns the corresponding FILE
     pointer.  The filename is unlinked immediately and the file
     is removed at the moment it is closed.

     Internally, it relies on the tmpnam() POSIX function to
     generate the filename and uses it in a safe fashion.  Please
     refer to the tmpnam man page for details about the tmpnam()
     function on your system.

     The function return a FILE pointer or 0 if no safe filename
     could be generated for whatever reason.

   * Function:

       FILE *fileg_safe_tmpfile_with_name(
         char *ret_filename, char *dest_path)

     This function works like fileg_safe_tmpfile() (including all
     limitations) with the following exceptions:

     If <dest_path> is not 0, the given path is used instead if
     P_tmpdir.

     The full path of the created temporary file is copied to the
     character array pointed to by <ret_filename> which must be
     big enough to hold at least L_tmpnam characters (L_tmpnam is
     usually defined in stdio.h).

 * Functions to test paths

   It is often for a program to accept path names from a user
   without testing them for sanity.  For example, a program that
   expects a plain file name may be given a relative path
   ("../foo").  A user may violate the program's security policy
   if a path is not properly filtered.  Fileguardian provides a
   couple of functions to simplify filtering.

   * Function:

     int fileg_remove_fuzz_from_path(char *path)

     This function removes unnecessary parts of a given path:

      - Multiple slashes are reduced to a single slash.
      - Occurences of "/./" are replaced with "/".
      - The paths "/.." and /. are reduced to just "/".
      - If the path begins with "/../" it is reduced to "/".
      - If the path begins with "./" it is removed.
      - Trailing slashes (/) are removed except if the path is
        just "/".
      - Trailing "/." are removed.

     If the path has been modified, 1 is returned, otherwise 0 is
     returned.

   * Functions:

     int fileg_is_absolute_path(const char *path)
     int fileg_is_relative_path(const char *path)
     int fileg_is_local_relative_path(const char *path)
     int fileg_is_path(const char *path)
     int fileg_is_filename(const char *path)

     These functions detect whether a given path is an absolute
     path, a relative path, a relative path below the current
     directory, any path or a filename.

     fileg_is_absolute_path returns 1 if path is an absolute path
     (begins with a slash '/').  Otherwise 0 is returned.

     fileg_is_relative_path returns 1 if path is a relative path
     (contains a slash but does not begin with a slash, or is just
     "." or "..").  Otherwise 0 is returned.

     fileg_is_local_relative_path returns 1 if path is a relative
     path below the current directory (does not contain a ".."
     component) or just a filename.  Otherwise 0 is returned.

     fileg_is_path returns 1 if path is any path (contains a slash
     '/' or is just "." or ".."). Otherwise 0 is returned.

     fileg_is_filename returns 1 if path is a filename (does not
     contain a slash and is neither "." nor "..").  Otherwise 0 is
     returned.

inputguardian.c
---------------

The functions in inputguardian.c are meant to simplify processing
program input in a safe fashion.

  The functions of the inputg_parse_... family are a replacement
  for the  ato... and strto... system functions that does proper
  range checking for the type of integer.  They read decimal
  integer values represented as a string into a variable of the
  appropriate type.

   * Functions:

     int inputg_parse_i(
       const char *string, const char **endptr,
       int *retval)

     int inputg_parse_ui(
       const char *string, const char **endptr,
       unsigned int *retval)

     int inputg_parse_l(
       const char *string, const char **endptr,
       long int *retval)

     int inputg_parse_ul(
       const char *string, const char **endptr,
       unsigned long int *retval)

     int inputg_parse_s(
       const char *string, const char **endptr,
       short int *retval)

     int inputg_parse_us(
       const char *string, const char **endptr,
       unsigned short int *retval)

     int inputg_parse_sc(
       const char *string, const char **endptr,
       signed char *retval)

     int inputg_parse_uc(
       const char *string, const char **endptr,
       unsigned char *retval)

     int inputg_parse_c(
       const char *string, const char **endptr,
       char *retval)

     The functions and the corresponding data types are:

     inputg_parse_i   -  int
     inputg_parse_ui  -  unsigned int
     inputg_parse_l   -  long int
     inputg_parse_ul  -  unsigned long int
     inputg_parse_s   -  short int
     inputg_parse_us  -  unsigned short int
     inputg_parse_sc  -  signed char
     inputg_parse_uc  -  unsigned char
     inputg_parse_c   -  char (signedness depends on compiler /
                         platform)

     The functions call the sscanf function to read the desired
     integer value from the argument "string" and store it in
     *retval.  If the conversion is successful, zero is returned,
     otherwise -1 is returned. In either case, if endptr is not
     NULL, a pointer to the first character that could not be
     parsed is stored in *endptr.

     If the conversion fails (either because the value found is
     out of range or no value could be parsed at all), 0 is stored
     in *retval.

     For maximum safety, test whether the return value is NULL.
     If not, it should point to a zero byte or a whitespace
     character in most cases.

     Example:

       unsigned int uival;
       const char *p;
       int rc;

       rc = inputg_parse_ui("123456", &p, &uival);
       if (rc != 0)
       {
         / * error * /
       }
       if (*p != 0 && *p != ' ' && *p != '\t' && *p != '\n')
       {
         / * is this ok? * /
       }

     Note: These functions may be too slow to parse large amounts
     of data.


  The following funtions of the inputg_escape_..._html... family
  parse a zero terminated input string and ensure it does not
  contain any (potentially malicious) scripting code by
  html-escaping the characters '<', '>', '&' and '"'.

  All funtions return the escaped string in malloc'ed memory or 0
  if no memory could be allocated.  It is the responsibility of
  the caller to free() the memory.

  Note:  The funtions are intended to be used to prevent cross
  site scripting (XSS).  The allowed set of characters is
  restricted to knows safe characters, so some valid and safe html
  documents may be escaped unnecessarily.  They do *not* validate
  that the document is well formed!

   * Function:

     char *inputg_escape_html(
       const char *input)

     inputg_escape_html() looks for html tags in the input string
     and escapes all occurences of html meta characters:

      <  becomes  &lt;
      >  becomes  &gt;
      "  becomes  &quot;
      &  becomes  &amp;

     except in the following tags:

       a abbr acronym b bdo big blink blockquote br center cite
       code dd del dfn dir dl dt em h1 h2 h3 h4 h5 h6 hr i ins kbd
       li menu nobr ol p plaintext pre q s samp small spacer
       strike strong sub sup tt u ul var.

     <a> tags are not escaped if they are plain links or
     references and escaped otherwise to filter out (potentially
     malicious) script code.  An input is accepted by the <a> tag
     if it matches one of the following two regular expressions,
     where S stands for the characters " \f\n\r\t\v".


      <a[S][S]*[hH][rR][eE][fF][S]*=[S]*[hH][tT][tT][pP]://[a-zA-Z0-9./-_]*[S]?[a-zA-Z0-9./-_]*>
      <a[S][S]*[hH][rR][eE][fF][S]*=[S]*"[hH][tT][tT][pP]://[a-zA-Z0-9./-_S]*[S]*">

   * Function:

     char *inputg_escape_all_html(
       const char *input)

     This function works exactly like inputg_escape_html() but
     escapes all occurences of the characters '<', '>', '&' and
     '"' without any excaptions.

   * Function:

     char *inputg_escape_html_with_tag_table(
	const char *input, const char * const *allowed_tags)

     This function works exactly like inputg_escape_html() but
     expects a user defined table of tags that need not be escaped
     in the parameter allowed_tags.  If the "a" tag is not in the
     table, <a> tags are escaped as well.  The table must be
     terminated with a 0 pointer.

     Example:

       const char * const allowed_tags[] =
       {
         "h1",
         "h2",
         ...
         "a",
         0
       };
       char *escaped;
       escaped = inputg_escape_html_with_tag_table(input, allowed_tags);
       if (escaped == 0)
       {
         /* out of memory */
       }


  Inputguardian provides a simple function to validate email
  addresses.  It's emphasis is on easy of use, not on
  completeness, so it rejects many valid email addresses.

   * Function:

     int inputg_is_simple_email_address(
       const char *addr)

     inputg_is_simple_email_address provides a very crude check
     for valid email addresses.  It accepts only addresses in the
     form

       name@domain_part[.domain_part]...

    Where name is a sequence of letters, digits and the characters
    '_', '+', '-' and '.' and domain_part is a sequence of
    letters, digits and the character e'-'.

    If the address conforms to this requirements the function
    returns 1.  Otherwise 0 is returned.


libgateguardian
---------------

All interface functions and types described above are inside the
libgateguardian library.  In addition, two functions and a shell
script to query the Gate Guardian version and the library version
are provided by the header file gateguardian/version.h:

  unsigned int gateg_libversion(void);

    Returns an unsigned integer number with at least 32 bits.

      Bits 24-31: major version
      Bits 16-23: minor version
      Bits  0-15: patchlevel

    Please refer to the section "Library Versioning Scheme" for
    the meaning of these numbers,

  unsigned int gateg_version(void);

    Returns an unsigned integer number with at least 32 bits.

      Bits 24-31: interface
      Bits 16-23: revision
      Bits  0-15: age

    Please refer to the section "Package Versioning Scheme" for
    the meaning of these numbers,

Also, a shell script is provided that prints all version
information and can be called with

  eval `gateguardian-version`

(in reverse quotes).  It defines a couple of environment variables:

  LIB_V_PACKAGE:  contains the string "gateguardian"
  LIB_V_MAJOR:    major version
  LIB_V_MINOR:    minor version
  LIB_V_PATCH:    patchlevel
  LIB_V_NUMBER:   the same number that gateg_version() returns
  LIB_LV_PACKAGE: contains the string "gateguardian"
  LIB_LV_AGE:     age
  LIB_LV_IF:      interface
  LIB_LV_REV:     revision
  LIB_LV_NUMBER:  the same number that gateg_libversion() returns


Package Versioning Scheme:
--------------------------

Version numbers are divided into three parts, the major release
number, the minor release number and the patchlevel.  The version
number is appended to the name of the tarballs:

  <project>-<major>.<minor>.<patchlevel>.tar.gz

For example

  gateguardian-0.9.3.tar.gz

A change in the major release number indicates major changes in
the interfaces.  Between minor releases, every effort should be
made to keep the interfaces compatible.  The patchlevels indicate
the day to day work between the releases.  Odd minor release
numbers like 2.1.0 indicate unstable development releases while
even numbers like 2.4.0 indicate stable releases.


Library Versioning Scheme
-------------------------

This package uses "libtool" to create all libraries, and adopts
the "Libtool Versioning System" for shared libraries.  Please
refer to doc/DEVELOPERS or libtool's documentation.


Contact, Downloading, Bug Reports
---------------------------------

The lastest releases (including GPG signature and MD5 sum), and
the release key file can be downloaded from the project site at:

  http://sourceforge.net/projects/gateguardian/

Email and bug reports can be sent to

  gateguardian-devel[AT]lists[DOT]sourceforge[DOT]net

(Replace [AT] with '@' and [DOT] with '.').
