##############################################################################
# Copyright (c) Members of the EGEE Collaboration. 2004.
# See http://www.eu-egee.org/partners/ for details on the copyright
# holders.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################
#
# NAME :        config_glexec_wn_lcaslcmaps
#
# DESCRIPTION : This function configures lcas and lcmaps for glexec in the WN.
#
# AUTHORS :     Maria.Alandes.Pradillo@cern.ch
#
# NOTES :       
#
# YAIM MODULE:  glite-yaim-clients
#
##############################################################################

config_glexec_wn_lcaslcmaps_check () {

  requires $1 GLEXEC_WN_LCAS_DIR GLEXEC_WN_LCAS_CONFIG X509_VOMS_DIR X509_CERT_DIR GRIDMAPFILE \
              GLEXEC_WN_LCMAPS_DIR GLEXEC_WN_LCMAPS_CONFIG GROUPMAPFILE
  if [ $? -eq 1 ]; then
    exit 1
  fi

  if [ "x${GLEXEC_WN_SCAS_ENABLED}" == "xyes" ]; then
    if [ -z "$SCAS_ENDPOINTS$SCAS_HOST" ]; then
	yaimlog ERROR "SCAS is enabled, but no endpoints are configured."
	yaimlog ERROR "Set either SCAS_ENDPOINTS or SCAS_HOST and SCAS_PORT"
	yestr ${YEX_CONFIG}
	exit ${YEX_CONFIG}
    fi
  fi

  if [ "x${GLEXEC_WN_ARGUS_ENABLED}" == "xyes" ]; then
    if [ -z "$ARGUS_PEPD_ENDPOINTS" ]; then
	yaimlog ERROR "ARGUS is enabled, but no endpoints are configured."
	yaimlog ERROR "Please define ARGUS_PEPD_ENDPOINTS."
	yestr ${YEX_CONFIG}
	exit ${YEX_CONFIG}
    fi
  fi

}


config_glexec_wn_lcaslcmaps_setenv () {
 yaimlog DEBUG "Currently this function doesn't set any environment variables."
 return 0
}

check_plugin_files () {
    missing=no
    comp=$1
    shift
    for plugin in "$@"
    do
	yaimlog DEBUG "checking presence of ${libdir}/${comp}/${plugin}"
	if ! test -f "${libdir}/${comp}/${plugin}" ; then
	    yaimlog ERROR "Missing ${comp} plugin ${plugin}"
	    missing=yes
	fi
    done
    if test $missing = yes ; then
	yaimlog ERROR "Some required plugin(s) were not found"
	yestr ${YEX_NOSUCHFILE}
	exit ${YEX_NOSUCHFILE}
    fi
}

config_glexec_wn_lcaslcmaps () {

####@ creating LCAS configuration directory
mkdir -p ${GLEXEC_WN_LCAS_DIR}

# A ban user file is required by lcas
####@ Creating the ban_users.db file
if [ ! -f ${GLEXEC_WN_LCAS_DIR}/ban_users.db ]; then
    yaimlog INFO "creating empty ban_users.db"
    touch  ${GLEXEC_WN_LCAS_DIR}/ban_users.db
fi



if [ "x${GLEXEC_WN_USE_LCAS}" = "xyes" ]; then
    yaimlog INFO "Generating LCAS config file"

####@ Generating LCAS config file

    yaimlog DEBUG "Backing up LCAS old configuration file."
    mv ${GLEXEC_WN_LCAS_CONFIG} ${GLEXEC_WN_LCAS_CONFIG}.old 2>/dev/null

    if [ "x${GLEXEC_WN_SCAS_ENABLED}" == "xyes" -o \
	"x${GLEXEC_WN_ARGUS_ENABLED}" == "xyes" ]; then
	cat <<EOF> ${GLEXEC_WN_LCAS_CONFIG}
#
# LCAS config file for glexec with SCAS or ARGUS generated by YAIM: `date`
#
pluginname=${libdir}/lcas/lcas_userban.mod,pluginargs=${GLEXEC_WN_LCAS_DIR}/ban_users.db
EOF
        # test the presence of the plugin
	check_plugin_files lcas lcas_userban.mod
    else
	cat <<EOF> ${GLEXEC_WN_LCAS_CONFIG}
#
# LCAS config file for glexec without SCAS or ARGUS generated by YAIM: `date`
#
pluginname=${libdir}/lcas/lcas_userban.mod,pluginargs=${GLEXEC_WN_LCAS_DIR}/ban_users.db
pluginname=${libdir}/lcas/lcas_voms.mod,pluginargs="-vomsdir ${X509_VOMS_DIR} -certdir ${X509_CERT_DIR} -authfile ${GRIDMAPFILE} -authformat simple"
EOF
        # test the presence of the plugin
	check_plugin_files lcas lcas_userban.mod lcas_voms.mod

    fi

fi # GLEXEC_WN_USE_LCAS = yes

yaimlog INFO "Generating LCMAPS config file"
####@ Generating LCMAPS config file
mkdir -p ${GLEXEC_WN_LCMAPS_DIR}

####@ set the possible SCAS endpoint if configured
# This is a bit complicated as we have to allow 'old style' SCAS_HOST
# as well as SCAS_ENDPOINTS. Merge the variables, than treat them as one.
if [ "$GLEXEC_WN_SCAS_ENABLED" = yes ]; then
    yaimlog DEBUG "configuring SCAS endpoints"
    tmpscasendpoints=
    if [ -n "$SCAS_HOST" ]; then
	yaimlog DEBUG "Using old-style SCAS_HOST:SCAS_PORT for endpoints"
	tmpscasendpoints="https://$SCAS_HOST:$SCAS_PORT"
    fi
    if [ -n "$SCAS_ENDPOINTS" ]; then
	tmpscasendpoints="$tmpscasendpoints $SCAS_ENDPOINTS"
    fi
    yaimlog DEBUG "configured endpoints: '$tmpscasendpoints'"
    scasendpoints=
    # separator just for nice formatting
    sep=
    for i in $tmpscasendpoints ; do
	scasendpoints="$scasendpoints$sep\"--endpoint $i\""
	sep="
             "
    done
fi

# This is easier than the SCAS situation as we don't include the old-style
# notation.
if [ "$GLEXEC_WN_ARGUS_ENABLED" = yes ]; then
    yaimlog DEBUG "configuring ARGUS endpoints"
    argusendpoints=
    # separator just for nice formatting
    sep=
    for i in $ARGUS_PEPD_ENDPOINTS ; do
	argusendpoints="$argusendpoints$sep\"--pep-daemon-endpoint-url $i\""
	sep="
             "
    done
fi

####@ Creating new LCMAPS configuration file
yaimlog DEBUG "Backing up old LCMAPS configuration file."
mv ${GLEXEC_WN_LCMAPS_CONFIG} ${GLEXEC_WN_LCMAPS_CONFIG}.old 2>/dev/null
touch ${GLEXEC_WN_LCMAPS_CONFIG}

yaimlog DEBUG "Setting permissions on the LCMAPS config file"
if [ "x${GLEXEC_WN_OPMODE}" == "xsetuid" ]; then
  chown root:root ${GLEXEC_WN_LCMAPS_CONFIG}
  chmod 0640 ${GLEXEC_WN_LCMAPS_CONFIG}
  chown root:root ${GLEXEC_WN_LCAS_CONFIG}
  chmod 0640 ${GLEXEC_WN_LCAS_CONFIG}
else
  chown root:root ${GLEXEC_WN_LCMAPS_CONFIG}
  chmod 0644 ${GLEXEC_WN_LCMAPS_CONFIG}
  chown root:root ${GLEXEC_WN_LCAS_CONFIG}
  chmod 0644 ${GLEXEC_WN_LCAS_CONFIG}
fi

# Begin writing the configuration; the verify-proxy module is
# included always.
yaimlog DEBUG " ... Include verify proxy module"
cat <<EOF >> ${GLEXEC_WN_LCMAPS_CONFIG}
#
# LCMAPS config file for glexec generated by YAIM: `date`
#

# where to look for modules
path = ${libdir}/lcmaps
 
# module definitions
verify_proxy = "lcmaps_verify_proxy.mod" 
               " -certdir ${X509_CERT_DIR}"
               " --allow-limited-proxy"

EOF
check_plugin_files lcmaps lcmaps_verify_proxy.mod

# If not setuid, and no SCAS and no ARGUS: just the dummy good module is needed.
# This also completes the policy, and this function.
if [ "x${GLEXEC_WN_OPMODE}" != "xsetuid" -a \
     "x${GLEXEC_WN_SCAS_ENABLED}" != "xyes" -a \
     "x${GLEXEC_WN_ARGUS_ENABLED}" != "xyes" ]; then

    yaimlog DEBUG " ... Include dummy good module"
    cat <<EOF >> ${GLEXEC_WN_LCMAPS_CONFIG}
good = "lcmaps_dummy_good.mod" 
       " --dummy-username nobody" 
       " --dummy-group nobody" 
       " --dummy-sec-group nobody" 

glexec_get_account: 
verify_proxy -> good 

EOF
    check_plugin_files lcmaps lcmaps_dummy_good.mod
    return $YEX_OK
fi

# If neither SCAS nor ARGUS is chosen, we need lots of plugins
# This also ends the function
if [ "x${GLEXEC_WN_SCAS_ENABLED}" != "xyes" -a \
     "x${GLEXEC_WN_ARGUS_ENABLED}" != "xyes" ]; then

    yaimlog DEBUG " ... Include vomslocalgroup {voms,}{local,pool}account modules"

    cat <<EOF >> ${GLEXEC_WN_LCMAPS_CONFIG}
good = "lcmaps_dummy_good.mod" 
       " --dummy-username nobody" 
       " --dummy-group nobody" 
       " --dummy-sec-group nobody" 

vomslocalgroup = "lcmaps_voms_localgroup.mod" 
                 " -groupmapfile ${GROUPMAPFILE}" 
                 " -mapmin 0" 

vomslocalaccount = "lcmaps_voms_localaccount.mod" 
                   " -gridmapfile ${GRIDMAPFILE}" 
                   " -use_voms_gid" 

vomspoolaccount = "lcmaps_voms_poolaccount.mod" 
                  " -gridmapfile ${GRIDMAPFILE}" 
                  " -gridmapdir ${GRIDMAPDIR}" 
                  " -do_not_use_secondary_gids" 

localaccount = "lcmaps_localaccount.mod"
               " -gridmapfile ${GRIDMAPFILE}"

poolaccount = "lcmaps_poolaccount.mod"
              " -override_inconsistency"
              " -gridmapfile ${GRIDMAPFILE}"
              " -gridmapdir ${GRIDMAPDIR}"

glexec_get_account:
verify_proxy -> vomslocalgroup
vomslocalgroup -> vomslocalaccount | localaccount
vomslocalaccount -> good | vomspoolaccount
localaccount -> good | poolaccount
EOF
    check_plugin_files lcmaps lcmaps_dummy_good.mod \
	lcmaps_voms_localgroup.mod \
	lcmaps_voms_localaccount.mod \
	lcmaps_voms_poolaccount.mod \
	lcmaps_localaccount.mod \
	lcmaps_poolaccount.mod

    yaimlog DEBUG "Finished LCMAPS configuration"
    return $YEX_OK
fi

# Remaining cases: scas with/without setuid, argus with/without setuid

# first the plugins, last the policies. If both SCAS and ARGUS are chosen,
# the policy is a combination (the logical AND) where first ARGUS, then SCAS
# must be passed.

if [ "x${GLEXEC_WN_SCAS_ENABLED}" == "xyes" ]; then
    ####@ Configuring glexec with SCAS if selected
    yaimlog INFO "glexec is configured to work with SCAS"
    yaimlog DEBUG " ... Include scas client module"
    cat <<EOF >> ${GLEXEC_WN_LCMAPS_CONFIG}
scasclient = "lcmaps_scas_client.mod"
             " -capath ${X509_CERT_DIR}"
             $scasendpoints
             " -resourcetype wn"
             " -actiontype execute-now"

EOF
    check_plugin_files lcmaps lcmaps_scas_client.mod

fi

if [ "x${GLEXEC_WN_ARGUS_ENABLED}" == "xyes" ]; then
    ####@ Configuring glexec with ARGUS if selected
    yaimlog INFO "glexec is configured to work with ARGUS"
    yaimlog DEBUG " ... Include lcmaps_c_pep module"
    # If libcurl is linked with NSS (rather than, say, OpenSSL)
    # we need a workaround as NSS can't handle proxies. The workaround
    # is to treat the proxy as the CA so chain verification can
    # succeed. See http://wiki.nikhef.nl/grid/GLExec_Argus_Quick_Installation_Guide
    GLEXEC_WN_PEPC_PROXY_IS_CA_FLAG=
    curlusesnss=no

    # The heuristics to figure out whether this flag is needed are
    # somewhat complicated, because there is no single clean way
    # to do this. So the order of tests becomes:
    # 1. if curl is installed, run curl -V and seek NSS in the first line
    # 2. otherwise, check the dynamic dependencies of libcurl.so

    if [ -x /usr/bin/curl ]; then
	if  /usr/bin/curl -V | head -n 1 | grep -q -F " NSS/" 2>/dev/null ; then
	    curlusesnss=yes
	fi
    else
	if find ${libdir} -maxdepth 1 -type f -name libcurl.so.\* -exec ldd {} \; | grep -q libnss ; then
	    curlusesnss=yes
	fi
    fi
    if [ $curlusesnss = yes ] ; then
	GLEXEC_WN_PEPC_PROXY_IS_CA_FLAG='" --use-pilot-proxy-as-cafile" # Add this on RHEL 6 based systems'
    fi
    cat <<EOF >> ${GLEXEC_WN_LCMAPS_CONFIG}
pepc        = "lcmaps_c_pep.mod"
              $argusendpoints
              " -resourceid $GLEXEC_WN_PEPC_RESOURCEID"
              " -actionid $GLEXEC_WN_PEPC_ACTIONID"
	      " -capath $X509_CERT_DIR"
	      " -pep-certificate-mode implicit"
              $GLEXEC_WN_PEPC_PROXY_IS_CA_FLAG
EOF
    check_plugin_files lcmaps lcmaps_c_pep.mod

fi

####@ Write the lcmaps policy
yaimlog DEBUG "writing the policy"

policy="glexec_get_account:"

if [ "x${GLEXEC_WN_ARGUS_ENABLED}" == "xyes" ]; then
    lastmodule="pepc"
else
    lastmodule="scasclient"
fi

policy="$policy
verify_proxy -> $lastmodule"

if [ "$GLEXEC_WN_ARGUS_ENABLED$GLEXEC_WN_SCAS_ENABLED" = yesyes ] ; then
    policy="$policy
pepc -> scasclient"
    lastmodule="scasclient"
fi

    cat <<EOF >> ${GLEXEC_WN_LCMAPS_CONFIG}

$policy
EOF

return $YEX_OK

}

