#!/bin/bash

# @file generic_create_diameterconf
#
# Copyright (C) Metaswitch Networks 2016
# If license terms are provided to you in a COPYING file in the root directory
# of the source code repository by which you are accessing this code, then
# the license outlined in that COPYING file applies to your use.
# Otherwise no rights are granted except for those provided to you by
# Metaswitch Networks in a separate written agreement.

# This file creates a freeDiameter config file, and appropriate
# TLS keys, for either Ralf, Homestead or Cedar.

usage="Usage: generic_create_diameterconf [homestead|ralf|cedar] DIAMETER_IDENTITY DIAMETER_REALM LISTEN_PORT SECURE_LISTEN_PORT INCOMING_CONNECTIONS CHECK_DESTINATION_HOST TW_TIMER
\nThe TW_TIMER parameter is the Diameter watchdog message delay in seconds.
\nIt must be an integer greater than or equal to 6."

name=$1
identity=$2
realm=$3
port=$4
sec_port=$5
acl_required=$6
check_dh=$7
tw_timer=$8

if [[ $# != 8 ]]
then
    # Usage message to stderr
    echo -e $usage >&2
    exit 1
fi

if [[ $tw_timer -lt 6 ]]
then
  echo "TW_TIMER is less than 6!" >&2
  echo -e $usage >&2
  exit 1
fi

key_dir=/var/lib/$name
cfg_dir=/var/lib/$name
fd_dir=/usr/share/clearwater/$name/lib/freeDiameter/

if /usr/share/clearwater/bin/is-address-ipv6 $identity
then
  identity=$(/usr/share/clearwater/bin/ipv6-to-hostname $identity)
fi

if /usr/share/clearwater/bin/is-address-ipv6 $realm
then
  realm=$(/usr/share/clearwater/bin/ipv6-to-hostname $realm)
fi

if [ -f $key_dir/privkey.pem ]
then
    priv_modulus=$(openssl rsa -in $key_dir/privkey.pem -modulus -noout)
fi

if [ -f $key_dir/cert.pem ]
then
    pub_modulus=$(openssl x509 -in $key_dir/cert.pem -modulus -noout)
    cert_current_name=$(certtool --certificate-info --infile $key_dir/cert.pem | egrep -e 'Subject: CN=' | sed 's/.*Subject: CN=//g')
    cert_issuer=$(certtool --certificate-info --infile $key_dir/cert.pem | egrep -e 'Issuer: CN=' | sed 's/.*Issuer: CN=//g')
fi

if [ -f $key_dir/ca.pem ]
then
    ca_name=$(certtool --certificate-info --infile $key_dir/ca.pem | egrep -e 'Subject: CN=' | sed 's/.*Subject: CN=//g')
fi

if [ "$cert_current_name" != "$identity" ] ||
   [ "$priv_modulus" != "$pub_modulus" ] ||
   [ "$cert_issuer" != "$ca_name" ]
then
    # The current certificate does not have the required common name,
    # or does not match the private key, or does not match the CA.  Remove them so that they are regenerated below.
    rm -f $key_dir/cert.pem $key_dir/privkey.pem $key_dir/ca.pem
fi

# If any of the certificate files are missing, create new self-signed ones.
if [ ! -f $key_dir/cert.pem ] ||
   [ ! -f $key_dir/privkey.pem ] ||
   [ ! -f $key_dir/ca.pem ]
then
  rm -f $key_dir/cert.pem $key_dir/privkey.pem $key_dir/ca.pem

  # Build up the configuration file for GnuTLS
  cat > /tmp/cert.cfg.$$ <<EOF
cn = "$identity"
expiration_days = 3650
EOF

  # Create the certificates.
  sudo certtool --generate-privkey --bits 1024 --template /tmp/cert.cfg.$$ --outfile $key_dir/privkey.pem
  sudo certtool --generate-self-signed --bits 1024 --template /tmp/cert.cfg.$$ --load-privkey $key_dir/privkey.pem --outfile $key_dir/cert.pem

  # Fix up the certificates in the directory.  The private key is created as readable
  # by root only.  Fix it so that the $name user can read it as well.
  chmod 644 $key_dir/privkey.pem
  cp $key_dir/cert.pem $key_dir/ca.pem
  rm /tmp/cert.cfg.$$
fi

# By default assume incoming connections from peers are not allowed, so comment out the
# acl_wl.fdx Load Extension line. If incoming connections are allowed, uncomment it.
acl_commenter="#";
if [[  $acl_required == "true" ]]
then
  acl_commenter=""
fi

# By default assume that the Destination-Host AVP should be checked on incoming requests,
# so comment out the rt_change_dh.fdx Load Extension line. If ignoring the Destination-Host
# is allowed, uncomment it.
dh_commenter="#";
if [[  $check_dh == "false" ]]
then
  dh_commenter=""
fi

# Set up the configuration for $name with the right IP addresses and ports
cat > $cfg_dir/$name.conf <<EOF
# -------- Local ---------

Identity = "$identity";
Realm = "$realm";

Port = $port;
SecPort = $sec_port;

# TLS configuration
TLS_Cred = "$key_dir/cert.pem", "$key_dir/privkey.pem";
TLS_CA = "$key_dir/ca.pem";
TLS_Prio = "NORMAL:-VERS-SSL3.0";

# Limit the number of SCTP streams
# SCTP_streams = 3;
No_SCTP;

# The delay between watchdog messages in seconds
TwTimer = $tw_timer;

# -------- Extensions ---------

# Uncomment (and create rtd.conf) to specify routing table for this peer.
#LoadExtension = "$fd_dir/rt_default.fdx" : "$cfg_dir/rtd.conf";

# Uncomment (and create acl.conf) to allow incoming connections from other peers.
$acl_commenter LoadExtension = "$fd_dir/acl_wl.fdx" : "$cfg_dir/acl.conf";

# Uncomment to display periodic state information
LoadExtension = "$fd_dir/dbg_monitor.fdx";

# Load the SIP and 3GPP dictionary objects
LoadExtension = "$fd_dir/dict_nasreq.fdx";
LoadExtension = "$fd_dir/dict_sip.fdx";
LoadExtension = "$fd_dir/dict_dcca.fdx";
LoadExtension = "$fd_dir/dict_dcca_3gpp.fdx";

# Uncomment to allow ignoring the Destination-Host AVP on incoming requests
$dh_commenter LoadExtension = "$fd_dir/rt_change_dh.fdx";

# If we receive an AVP that is marked as mandatory from one of these vendors,
# we ignore the mandatory flag.
UntrustedAVPVendors = 19444;

EOF
