#! /bin/sh

# Copyright (c) 2008-2013
# Distributed Systems Software.  All rights reserved.
tag='$Id: dacsinit 2629 2013-01-24 22:15:44Z brachman $'

# Configure a minimal DACS federation interactively
# Usage: dacsinit [-d] [-n]
#
# This pretty much does the procedure explained in Step 5 of dacs.quick(7),
# except that it uses the actual build-time paths instead of the defaults
# used in dacs.quick(7).
#
# It could be extended to also do some or all of Step 6 (configuring
# some DACS-wrapped URLs for the new jurisdiction).
#
# XXX Very little error checking is done, especially for invalid input

# If DEBUG is set, we will use it as a suffix to avoid zapping any "real" files
# You may change DEBUG_SUFFIX
debug=
debug_suffix="-xxx"

# These are defaults that ought to be overridden by defs.vars later
xinstall="./conftools/install-sh"
xsetaccess="./conftools/setaccess-sh"
xecho_n="../src/conftools/echo_n-sh"

xmv="mv"
xrm="rm"
xdacskey="./dacskey"

# Stoopid incompatibility workarounds...
# On Solaris, at least, the builtin implementation of test(1) is busted
if test -x /bin/test
then
  xtest="/bin/test"
elif test -x /usr/bin/test
then
  xtest="/usr/bin/test"
else
  xtest="test"
fi

# You may change these
backup_suffix="-bak"

# These are reasonable defaults; change them here or manually edit the output
jurisdiction_authenticates="yes"
jurisdiction_prompts="no"
jurisdiction_dacs_url_port="18123"
jurisdiction_dacs_url_path="cgi-bin/dacs"

# Prompt with arg1, use arg2 as the default, and return the value
ask() {

  $xecho_n "$1" "[$2]? " > /dev/tty
  read val
  if $xtest "${val}" = ""
  then
    echo $2
  else
    echo ${val}
  fi
}

emit_insns() {

  if $xtest -x /usr/bin/fmt
  then
    fmt="/usr/bin/fmt"
  else
    fmt="cat"
  fi

  (cat <<HERE
This program will create a minimal federation with one jurisdiction.  You will be prompted for some basic configuration values.  It is assumed that you have already reviewed the DACS documentation and have some understanding of what these values mean.  You must have already done a 'make install' of DACS.

The default values are for the example configuration used in dacs.quick(7).  For more information, see: dacs.readme(7), dacs(1), dacs.conf(5), and dacs.quick(7).

If you have not configured DACS on your system, it is safe to run this more than once; once you have a working DACS configuration, you should not run this because you may lose your existing configuration.

You can change, customize, or extend the federation or jurisdiction produced by this program.  The relevant filenames will be listed.

Warning: existing DACS configuration files may be deleted.
HERE
  ) | $fmt

}

# If arg1 exists, save a copy
backup() {
  target="$1"
  target_backup="${1}${backup_suffix}"

  if $xtest -e "${target}"
  then
    if $xtest -d "${target}"
    then
      echo "Renaming ${target} to ${target_backup}"
      $xrm -r -f "${target_backup}"
      $xmv "${target}" "${target_backup}"
    else
      echo "Copying ${target} to ${target_backup}"
      $xrm -f "${target_backup}"
      $xinstall -c -g "${dacsgroup}" -m 0640 "${target}" "${target_backup}"
    fi
  fi

}

emit_usage() {
  msg="$1"

  echo "$msg"
  echo "Usage: dacsinit [-d] [-n]"
  exit 1
}

emit_dacs_conf() {

  echo '<Configuration xmlns="http://fedroot.com/dacs/v1.4">'
  echo ''

  echo '<Default>'
  echo "  FEDERATION_NAME \"${federation_name}\""
  echo "  FEDERATION_DOMAIN \"${federation_domain}\""
  echo '</Default>'
  echo ''

  echo "<Jurisdiction uri=\"${jurisdiction_uri}\">"
  echo "  JURISDICTION_NAME \"${jurisdiction_name}\""
  echo '</Jurisdiction>'

  echo ''
  echo '</Configuration>'
}

# Emit a DACS meta description for this minimal federation
emit_meta() {

  echo '<groups xmlns="http://dss.ca/dacs/v1.4">'
  echo "<group_definition jurisdiction=\"${jurisdiction_name}\""
  echo " name=\"jurisdictions\""
  now=`date '+%a, %e-%b-%G %k:%M:%S %Z'`
  echo " mod_date=\"${now}\""
  echo " type=\"public\">"
  echo "<group_member jurisdiction=\"${jurisdiction_name}\""
  echo " name=\"${jurisdiction_desc}\""
  echo " type=\"meta\""
  echo " alt_name=\"${jurisdiction_altdesc}\""
  echo " dacs_url=\"${jurisdiction_dacs_url}\""
  echo " authenticates=\"${jurisdiction_authenticates}\""
  echo " prompts=\"${jurisdiction_prompts}\""
  echo " public_key=\"${j_pub_key}\"/>"
  echo '</group_definition>'
  echo '</groups>'
}

nflag=
for i
do
  case "${i}" in
  -d)
     debug="${debug_suffix}"
     ;;

  -n)
     if $xtest "${nflag}" = ""
     then
       xinstall="echo $xinstall"
       xmv="echo $xmv"
       xrm="echo $xrm"
       xdacskey="echo $xdacskey"
       nflag="yes"
     fi
     ;;

  *)
     emit_usage "Invalid argument"
     # NOTREACHED
     exit 1
     ;;
  esac 
done

emit_insns

proceed=`ask 'Enter "yes" or "y" if you want to proceed' 'no'`
case "${proceed}" in
[yY]*)
  ;;
*)
  exit 1
  ;;
esac

# 0. Begin by fetching some build-time configuration values for
# DACS_CONF, DACS_SITE_CONF, FEDERATIONS_ROOT and various tools
if $xtest ! -e ./defs.vars
then
  echo "No defs.vars file found... has DACS been installed?"
  echo "dacsinit must be run from the DACS src directory"
  exit 1
fi

. ./defs.vars
if $xtest $? -ne 0
then
  echo "An error occurred while processing defs.vars"
  exit 1
fi

if $xtest ! -e ./.groupname
then
  echo "No .groupname file found... has DACS been installed?"
  echo "dacsinit must be run from the DACS src directory"
  exit 1
fi

if $xtest "${dacs_conf}" = ""
then
  echo "dacs_conf is not defined in defs.vars - has DACS been installed?"
  exit 1
fi

dacsgroup=`cat ./.groupname`

echo ""
if $xtest "${debug}" != ""
then
  echo "Debug mode is enabled."
  echo "The suffix \"${debug}\" will be appended."
fi

echo "Suffix for backed up files and directories is \"${backup_suffix}\""

# 1. Prompt for basic dacs.conf configuration values
dacs_conf=`ask "dacs.conf" "${dacs_conf}"`${debug}
dacs_site_conf=`ask "site.conf" "${dacs_site_conf}"`${debug}
if test "${dacs_conf}" = "${dacs_site_conf}"
then
  echo "dacs.conf and site.conf cannot be the same file!"
  exit 1
fi

federation_name=`ask 'FEDERATION_NAME' 'DACSTEST'`
federation_domain=`ask 'FEDERATION_DOMAIN' 'dacstest.dss.ca'`
jurisdiction_name=`ask 'JURISDICTION_NAME' 'LA'`
jurisdiction_hostname=`ask "Jurisdiction's hostname" "dodgers"`
jurisdiction_uri="${jurisdiction_hostname}.${federation_domain}"
jurisdiction_dacs_url=`ask "Jurisdiction's DACS URL" "http://${jurisdiction_uri}:${jurisdiction_dacs_url_port}/${jurisdiction_dacs_url_path}"`
jurisdiction_desc=`ask "Jurisdiction's descriptive name" "${jurisdiction_name} Jurisdiction"`
jurisdiction_altdesc=`ask "Jurisdiction's alternate descriptive name" "Jurisdiction for ${jurisdiction_name}"`

echo ""
echo "The following values will be used:"
echo "DACS_HOME         ${dacs_home}"
echo "DACS_CONF         ${dacs_conf}"
echo "DACS_SITE_CONF    ${dacs_site_conf}"
echo "FEDERATIONS_ROOT  ${dacs_federations_root}"

f_dir="${dacs_federations_root}/${federation_domain}${debug}"
backup "${f_dir}"

j_dir="${f_dir}/${jurisdiction_name}"

echo "FEDERATION_NAME   $federation_name"
echo "FEDERATION_DOMAIN $federation_domain"
echo "JURISDICTION_NAME $jurisdiction_name"
echo "JURISDICTION_URI  $jurisdiction_uri"
echo "Federation path   ${f_dir}"
echo "Jurisdiction path ${j_dir}"
echo ""


# 2. Install the default site configuration file.
#    Then copy ../conf/site.conf-std to ${DACS_HOME}/federations/site.conf
#    after saving any existing copy

backup "${dacs_site_conf}"
$xinstall -c -g ${dacsgroup} -m 0640 ../conf/site.conf-std "${dacs_site_conf}"

# 3. Create a minimal dacs.conf
backup "${dacs_conf}"
$xinstall -c -g "${dacsgroup}" -m 0640 /dev/null "${dacs_conf}"
if $xtest "${nflag}" = ""
then
  emit_dacs_conf > "${dacs_conf}"
else
  echo ""
  echo "Would emit dacs.conf to ${dacs_conf} as follows:"
  emit_dacs_conf
  echo ""
fi

# 4. Run dacskey to make federation encryption keys
$xinstall -d -g "${dacsgroup}" -m 0770 "${federations_root}"
$xinstall -d -g "${dacsgroup}" -m 0770 "${f_dir}"
$xinstall -c -g "${dacsgroup}" -m 0640 /dev/null "${f_dir}/federation_keyfile"
$xdacskey -c ${dacs_conf} -uj ${jurisdiction_name} -q "${f_dir}/federation_keyfile"

# 5. Run dacskey to make jurisdiction encryption keys
$xinstall -d -g "${dacsgroup}" -m 0770 "${j_dir}"
$xinstall -c -g "${dacsgroup}" -m 0640 /dev/null "${j_dir}/jurisdiction_keyfile"
$xdacskey -c "${dacs_conf}" -uj "${jurisdiction_name}" -q "${j_dir}/jurisdiction_keyfile"
j_pub_key=`$xdacskey -c "${dacs_conf}" -uj "${jurisdiction_name}" -pub "${j_dir}/jurisdiction_keyfile"`

# 6. Create an empty ACL directory and revocation file
$xinstall -d -g "${dacsgroup}" -m 0770 "${j_dir}/acls"
$xinstall -c -g "${dacsgroup}" -m 0660 /dev/null "${j_dir}/acls/revocations"

# 7. Create and install a minimal DACS group to describe the jurisdiction
$xinstall -d -g "${dacsgroup}" -m 0770 "${j_dir}/groups" "${j_dir}/groups/${jurisdiction_name}" "${j_dir}/groups/DACS"
$xinstall -c -g "${dacsgroup}" -m 0660 /dev/null "${j_dir}/groups/DACS/jurisdictions.grp"
if $xtest "${nflag}" = ""
then
  emit_meta > "${j_dir}/groups/DACS/jurisdictions.grp"
else
  echo ""
  echo "Would emit jurisdictions.grp to ${j_dir}/groups/DACS/jurisdictions.grp as follows:"
  emit_meta
  echo ""
fi

# 8. Print a summary

if $xtest "${nflag}" = ""
then
  echo ""
  echo "You may now change or customize any of these files or directories:"
  echo "dacs.conf   ${dacs_conf}"
  echo "ACLS        ${j_dir}/acls"
  echo "Revocations ${j_dir}/acls/revocations"
  echo "Groups      ${j_dir}/groups"
  echo "Meta        ${j_dir}/groups/DACS/jurisdictions.grp"

  echo ""
  echo "To test this configuration, you can run:"
  echo "dacsconf -c ${dacs_conf} -uj ${jurisdiction_name}"
fi

exit 0
