#!/usr/bin/bash

##############################################################################
# This file is part of the CRYPTO BONE
# File     : safewebdropregistration (server) 
# Version  : 2.2 (ALL-IN-ONE)
# License  : BSD-3-Clause
# Date     : 29 May 2026
# Contact  : Please send enquiries and bug-reports to innovation@senderek.ie
#
# Copyright (c) 2015-2026
#	Ralf Senderek, Ireland.  All rights reserved. (https://senderek.ie)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	   This product includes software developed by Ralf Senderek.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND  ANY EXPRESS OR 
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  IMPLIED WARRANTIES 
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.
##############################################################################

ADMINNAME=root
PUBKEY=""
ID=""
REQ=""
KEY=""


#----------------------------------------------------#
# load functions and global variables
. ./safewebdrop-functions
#----------------------------------------------------#

# import system config file
if [[ -s /etc/safewebdrop.config ]] ; then
    . /etc/safewebdrop.config
else
     DEST="/var/safewebdrop"
fi


DEST="${DEST}/admin"
LOG=${DEST}/log


if [[ ! -d ${DEST} ]] ; then
     /usr/bin/echo "CONFIGURATION ERROR: the admin directory ${DEST} does not exist." | mail ${ADMINNAME}
     exit 3
fi

log "---- registration request  ----"

/usr/bin/echo Content-type: text/html
/usr/bin/echo

# extract ID and REQ (and KEY in phase 2) from QUERY_STRING
OLDIFS="${IFS}"
IFS=\&
set -- $QUERY_STRING 
ID=$1
REQ=$2
HASHSIG=$3
KEY=$4
IFS=${OLDIFS}

# get the client's IP
IP=$REMOTE_ADDR

if [[ ! ${ID} ]]; then
    # no user ID available
    log "No user ID in registration. Exiting ..."
    exit 2 
fi
if [[ ${ID} = admin* ]] ;then
    # forbidden
    log "someone (${IP}) wants to register ${ID}"
    exit 2
fi

FILE=${DEST}/${ID}.registration
log "using registration file $FILE"

# request = REGISTRATION or it consists of signed data
if [[ ${REQ} = "REGISTRATION" ]]; then
     # phase 1
     generate_challenge     

     # log the registration information in ${FILE}, overwrite any existing registration
     # so only the last one is valid
     /usr/bin/touch ${FILE} >/dev/null 2>/dev/null
     if [[ -r ${FILE} ]] ; then 
          /usr/bin/echo "ID=${ID}" > $FILE
	  /usr/bin/echo "ADDR=${IP}" >> $FILE   
          /usr/bin/echo "NONCE=${NONCE}" >> $FILE   
          /usr/bin/echo "CHALLENGE=${CHALLENGE}" >> $FILE   
	  log "providing a challenge for ${ID} for registration."
	  /usr/bin/echo -n "${CHALLENGE}"
	  exit 0
     fi
fi

if [[ ${REQ} != "REGISTRATION" ]] ; then

     # phase 2
     log "phase 2 signed request ${#REQ} bytes received" 
     # load the stored credentials
     if [[ -r ${FILE} ]] ; then
          .  ${FILE}
     else
          # no previous registration information is available
	  log "false request for ${ID} at IP :${IP}"
     fi

     # check if the new request has the same ADDR as in the stored registration information
     if [[ ${IP} != ${ADDR}  ]] ; then
         # dismiss this request
         log "different IP in phase 2 for user ${ID}"
         exit 4
     fi

     # save the user's PUBKEY in the admin directory
     PUBKEY=${DEST}/${ID}.pubkey.pem
     # store the new pubkey first, before the request is verified
     /usr/bin/echo -n "${KEY}" | /usr/bin/base64 -d > ${PUBKEY}
     
     # the tmp directory is used for verification, as no user directory exists at this point
     /usr/bin/ln -s ../tmp ${DEST}/${ID}
     if verify_request ; then
          rm -f ${DEST}/${ID}
          log "verification of signed request succeeded"

          # split the request
          OLDIFS="${IFS}"
          IFS=\:
          set -- ${REQ} 
          WID=$1
          WCHL=$2
          IFS=${OLDIFS}

          if [[ ${WID} != ${ID} ]] || [[  ${WCHL} != ${CHALLENGE} ]]  ; then
               # request failed
	       log "registration failed for user ${ID}"
	       /usr/bin/echo "none"
               cleansig
               rm -f ${DEST}/${ID}
	       exit 3
          fi

          # create a registration code and store it
          REGCODE=$(/usr/bin/dd if=/dev/urandom bs=1 count=20 2>/dev/null | /usr/bin/base64 | /usr/bin/cut -c-20 )
          /usr/bin/echo "REGCODE=${REGCODE}" >> $FILE 
          log "registration succeeded for user ${ID}"
          log "--- registration end ---"
          /usr/bin/echo -n ${REGCODE}
     else
          rm -f ${DEST}/${ID}
          # no valid request, log and be silent to give no indication of failure
	  log "registration failed for user ${ID} : corrupt/invalid request."
	  exit 3
     fi
fi     

cleansig
exit 0
