#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2024 - Greg Kroah-Hartman <gregkh@linuxfoundation.org>
#
# cve_create - Create a CVE entry to be submitted to the CVE database based on
# a provide git commit id
#
# Will look through the list of reserved cve ids and find the one for the year
# that the git commit was authored.  If none is availble, will exit with an
# error.
#
# If a free one is found, the new "database" entry will be created with files
# in the format that can be submitted both to CVE and for the mail
# notification.
#
# Usage:
#	cve_create [GIT_SHA] [CVE_ID]
#
# Requires:
#  A kernel git tree with the SHA to be used in it
#  bippy

KERNEL_TREE=${CVEKERNELTREE}

if [ ! -d ${KERNEL_TREE} ]; then
       echo "CVEERNELTREE needs setting to the stable repo directory"
       echo "Either manually export it or add it to your .bashrc/.zshrc et al."
       echo "See HOWTO in the root of this repo"
       exit 1
fi

# Colors are good!
txtred=$(tput setaf 1)		# Red
txtgrn=$(tput setaf 2)		# Green
txtblu=$(tput setaf 4)		# Blue
txtcyn=$(tput setaf 6)		# Cyan
txtrst=$(tput sgr0)		# Text reset

# don't use unset variables
set -o nounset

# set where the tool was run from,
# the name of our script,
# and the git version of it
DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
SCRIPT=${0##*/}

help() {
	echo "${SCRIPT} [GIT_SHA] [CVE_ID]"
	echo "	[CVE_ID] is optional, if not set, next one found will be assigned"
	exit 1
}

GIT_SHA="${1:-}"
if [[ "${GIT_SHA}" == "" ]] ; then
	help
fi

ID="${2:-}"

# See if the SHA given to us is a valid SHA in the git repo
# and turning the sha into a "full" one so that we don't get this wrong.
GIT_SHA_FULL=$(cd ${KERNEL_TREE} && git log -1 --format="%H" "${GIT_SHA}")
if [[ "${GIT_SHA_FULL}" == "" ]] ; then
	echo "error: git id ${GIT_SHA} is not found in the tree at ${KERNEL_TREE}"
	exit 1
fi

GIT_COMMIT=$(cd ${KERNEL_TREE} && git show -s --abbrev-commit --abbrev=12 --pretty=format:"%h (\"%s\")%n" "${GIT_SHA_FULL}")

YEAR=$(cd ${KERNEL_TREE} && git log -1 --format="%as" "${GIT_SHA_FULL}" | cut -f 1 -d '-')
if [[ "${YEAR}" == "" ]] ; then
	echo "error: can not determine the date of the commit!"
	exit 1
fi
#echo "year = ${YEAR}"

CVE_ROOT="${DIR}/../cve/"

RESERVED_DIR="${CVE_ROOT}reserved/${YEAR}/"
PUBLISHED_DIR="${CVE_ROOT}published/${YEAR}/"

# make sure we haven't allocated a CVE already for this id
found=$(${DIR}/cve_search ${GIT_SHA_FULL})
found_result=$?
if [[ "${found_result}" == "0" ]]; then
	exist=$(echo "${found}" | awk '{print $1}')
	echo "${txtred}ERROR:${txtrst} The git id ${txtcyn}${GIT_SHA_FULL}${txtrst} is already assigned to ${txtgrn}${exist}${txtrst}"
	exit 1
fi

# Go into the directory for the year asked for
cd "${RESERVED_DIR}" 2> /dev/null
if [[ $? -ne 0 ]]; then
	echo -n "${txtred}ERROR:${txtrst} Directory ${txtcyn}${RESERVED_DIR}${txtrst} not found, "
	echo "should you allocate some more for that year?"
	exit 1
fi

# find a free id if one is not already asked for
if [[ "${ID}" == "" ]]; then
	ID=$(ls | sort -V | head -n 1)

	if [[ "${ID}" == "" ]] ; then
		echo -n "${txtred}ERROR:${txtrst} No free id found for ${txtcyn}${YEAR}${txtrst}, "
		echo "should you allocate some more for that year?"
		exit 1
	fi
fi
#echo "ID=${ID}"

# Make the new year directory, if it is not present
# fixme, test if present first, as we shouldn't be rude here
mkdir "${PUBLISHED_DIR}" 2> /dev/null

# write the new entry, using the SHA given to us
# by moving the original entry and then writing to it
mv "${ID}" "${PUBLISHED_DIR}"
echo "${GIT_SHA_FULL}" > "${PUBLISHED_DIR}/${ID}.sha1"

# write the new json and mbox entry out, using bippy
"${DIR}"/bippy --cve="${ID}" --sha="${GIT_SHA_FULL}" --json="${PUBLISHED_DIR}/${ID}.json" --mbox="${PUBLISHED_DIR}/${ID}.mbox"
result=$?
if [[ "${result}" != 0 ]]; then
	# move the id back to the reserved area and delete the .sha1 file
	mv "${PUBLISHED_DIR}/${ID}" "${RESERVED_DIR}"
	rm "${PUBLISHED_DIR}/${ID}.sha1"
	echo "${txtred}Error:${txtrst} bippy failed to create ${txtcyn}${ID}${txtrst} for commit ${txtgrn}${GIT_COMMIT}${txtrst}"
	exit 1
fi

# say all is good, and give the id
echo "${txtcyn}${ID}${txtrst} is now allocated for commit ${txtgrn}${GIT_COMMIT}${txtrst}"
