#!/usr/bin/perl -w
# dumps all CVSS scores for all released updates into CSV.
use strict;

use Data::Dumper;

my $dn = `dirname $0`;chomp($dn);
my $pwd = `pwd`;chomp($pwd);
if ($dn !~ /^\//) { $dn = $pwd . "/" . $dn; }
push @INC,$dn;

require CanDBReader;
require CVEListReader;

require SMASHData;

&read_all_cached_issues();

my %matches = (
	"sles15-sp3" => "^(SUSE.Linux.Enterprise.*15.SP3)",
	"sles12-sp2" => "^(SUSE.Linux.Enterprise.Server.*12.SP[23]|ERICS)",
	"sles12-sp3" => "^SUSE.Linux.Enterprise.Server.*12.SP[34]",
	"sles12-sp4" => "^SUSE.Linux.Enterprise.Server.*12.SP[45]",
	"sles11-sp4" => "^SUSE.Linux.Enterprise.Server.*11.SP[34]",
);

foreach my $sp ("sles12-sp2","sles11-sp4")  {
	my $match = $matches{$sp};

	my $directsp = $sp;

	$directsp =~ s/sles//; $directsp =~ s/-/./;

	my @nolivepatch = ();
	my @nocvssv3 = ();
	my @nocvssv3other = ();


	my %cve2cvss = ();
	my %cve2cvssnvd = ();

	my %allcvss7 = ();

	my @allcves = ();

	#open(CVSS,">allreports.txt");
	foreach my $cve (sort keys %CanDBReader::bugzillas) {
		read_smash_issue($cve);

		# embargoed flag is not cleared after going public, check if we have an advisory listed or a note.
		if (	$SMASHData::embargoedcves{$cve} &&
			!defined($CanDBReader::advisoryids{$cve}) &&
			!defined($CanDBReader::note{$cve})
		) {
			next;
		}

		if (!defined($SMASHData::state{$cve})) {
			print STDERR "no smash state for $cve?\n" if -t STDERR;
			next;
		}

		#$cve =~ /CVE-(\d*)-/;
		#my $year = $1;
		#next if ($year < 2019);

		my $refetchsmash = 0;

		if (!defined($SMASHData::pkgstate{$cve})) {
			next;
		}
		my %prods = %{$SMASHData::pkgstate{$cve}};

		my $basescore 		= "unknown";
		my $basevector		= "unknown";
		my $nvdbasescore	= "unknown";
		my $nvdbasevector	= "unknown";

		if (defined($SMASHData::cvssv3{$cve}))  {
			my %entry = %{$SMASHData::cvssv3{$cve}};
			my %score;
			my %nvdscore;

			if (defined($entry{'SUSE'})) {
				%score = %{$entry{'SUSE'}};
				$basescore = $score{'base_score'};
				$basevector = $score{'base_vector'};
			}
			if (defined($entry{'National Vulnerability Database'})) {
				%nvdscore = %{$entry{'National Vulnerability Database'}};
				$nvdbasescore = $nvdscore{'base_score'};
				$nvdbasevector = $nvdscore{'base_vector'};
			}
		}
		# { PROD -> { PKG -> STATE } }

		my %foundone = ();

		my %fixedinsp2 = ();
		foreach my $prod (keys %prods) {
			#print "$cve - $prod\n";
			next unless ($prod =~ /$matches{$sp}/);
			print STDERR "$cve - $prod - ok\n" ; #if -t STDERR;
			next if ($prod eq "SLES_TERADATA-10-SP3");

			my %pkgstates = %{$prods{$prod}};
			#print STDERR "$prod\n";


			foreach my $pkg (sort keys %pkgstates) {
				my $state = $pkgstates{$pkg};

				# special hack, as GEHC does not have those, are only interested in kernel-source. (we always have kernel-default)
				next if ($pkg eq "kernel-source-azure");
				next if ($pkg eq "kernel-source-rt");
				next if ($pkg eq "kernel-source");
				next if ($pkg =~ /kgraft-patch/);

				next if ($state eq "Not affected");
				next if ($state eq "Already fixed");
				next if ($state eq "Unsupported"); # Unsupported means was affected previously, now not affected.
				next if ($state eq "Ignore");

				next if ($state eq "Analysis");	# FIXME

				print STDERR "$cve - $prod - $pkg - $state\n"; # if -t STDERR;
	# also getting these as SP2 ... they should not be ignored.
	#CVE-2021-3497 - SUSE Linux Enterprise Server 12 SP2 LTSS ERICSSON - gstreamer-plugins-good - Affected
	#CVE-2021-3497 - SUSE Linux Enterprise Server 12 SP2 BCL - gstreamer-plugins-good - Affected
	#CVE-2021-3497 - SUSE Linux Enterprise Server 12 SP2 LTSS SAP - gstreamer-plugins-good - Affected
				if ($state eq "Released") {
					# we released it for SP2, ignore it...
					if (($prod =~ /$directsp/i)  && ($prod !~ /EXTREME/i)) {
						print STDERR "$cve in $pkg RELEASED for $prod ($sp) already\n"; # if -t STDERR;
						$fixedinsp2{$pkg} = 1;
						next;
					}
				}

				print STDERR "\tADDED $pkg -> $pkgstates{$pkg}\n"; # if -t STDERR;

				$allcvss7{$cve}->{$pkg} = 1;
				$foundone{$pkg} = 1;
			}
		}
		#read_smash_issue($cve,1);

		foreach my $pkg (keys %foundone) {
			print STDERR "CHECKING $cve $pkg...\n" ; #if -t STDERR;
			if ($fixedinsp2{$pkg}) {
				print STDERR " REMOVING $pkg (was fixed: $fixedinsp2{$pkg})\n";# if -t STDERR;
				delete $foundone{$pkg};
				delete $allcvss7{$cve}->{$pkg};
			}
		}
		print STDERR Dumper(\%foundone) if -t STDERR;
		next unless (%foundone);

		my $nvdbasenum = -1;
		if ($nvdbasescore  =~ /^(\d+.*)/) {
			$nvdbasenum = $1;
		}
		$cve2cvssnvd{$cve} = $nvdbasenum;

		my $basenum = -1;
		if ($basescore  =~ /^(\d+.*)/) {
			$basenum = $1;
		}
		if ($basenum < 7.0) { # delete it again
			if (($nvdbasenum >= 7.0) && ($basenum == -1)) {
				print STDERR "SUSE UNRATED $cve , NVD score $nvdbasenum\n";
			}
			delete $allcvss7{$cve};
			next;
		}
		$cve2cvss{$cve} = $basenum;

		push @allcves,$cve;

		#read_smash_issue($cve,1) if ($refetchsmash);
	}

	my @sortedcves = sort {$CanDBReader::firstdate{$a} cmp $CanDBReader::firstdate{$b}}  @allcves;

	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
	$year += 1900;
	$mon += 1;

	my $fn = sprintf("service-pack-$sp-%04d-%02d-%02d.csv",$year,$mon,$mday);

	open(ATTACHMENT,">$fn");
	print ATTACHMENT "# first-bug-seen-date,CVE,SUSE-CVSS3-base-score,NVD-CVSS3-base-score,first-bug-with-this-CVE,sourcepackage,URL,Description\n";
	for my $cve (@sortedcves) {
		my @bugs = sort split(/,/,$CanDBReader::bugzillas{$cve});
		my $firstbug = $bugs[0];

		#
		# Only write out issues after 20210101
		#
		next if ($CanDBReader::firstdate{$cve} < 20210101);

		my $desc = get_description($cve);

		$desc =~ s/"/\\"/g;

		foreach my $pkg (sort keys %{$allcvss7{$cve}}) {
			print ATTACHMENT "$CanDBReader::firstdate{$cve},$cve,$cve2cvss{$cve},$cve2cvssnvd{$cve},$firstbug,$pkg,https://www.suse.com/security/cve/$cve,\"$desc\"\n";
		}
		#read_smash_issue($cve,1);
	}
	close(ATTACHMENT);
}
