#!/usr/bin/perl -w

# this is all SMASH querying and caching
# there is also hardcoed product -> CPE map which could come from SCC:

package SMASHData;

use strict;
use JSON;
use Data::Dumper;
use LWP;
use LWP::UserAgent;
use DateTime;
use HTTP::Date;

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

# meissner token:
#my $token="59d4672b1182bc0be2832cdc737c393c7f8df401";

# maintenance-robot token:
my $token="52658fad18b889e9ae8f835ade3a8a75a105f057";

# 12 hours
my $refreshtime = 7*24*60*60;

my $ua = LWP::UserAgent->new("keep_alive" => 1);
$ua->agent("cve-database/SMASHData.pm");
$ua->timeout(300);	# we have very long queries... but lets keep it to 5 minutes

sub get_url($) {
	my ($url) = @_;

	# print STDERR "getting $url\n";
# Create a request
	my $req = HTTP::Request->new(GET => $url);
	$req->header( 'Accept' => 'application/json' );
	$req->header( 'Authorization' => "Token $token" );
	my $res = $ua->request($req);
	if ($res->is_success) {
		if ($res->content eq "") {
			print STDERR "empty result on retrieving $url?\n";
		}
		return $res->content;
	} else {
		print STDERR "ERROR on: $url:\n";
		print STDERR $res->status_line;
		print STDERR "\n";
		return "";
	}
}

sub get_url_curl($) {
	my ($url) = @_;

	print STDERR "curl --insecure -s -H 'Authorization: Token SMASHTOKEN' \"$url\"|";
	open(CURL,"curl -s -H 'Authorization: Token $token' \"$url\"|");
	my @lines = <CURL>;
	close(CURL);
	return join("",@lines);
}



#state: Analysis
#state: Ignore
#state: Merged
#state: Pending
#state: Postponed
#state: Reopen
#state: Resolved
#state: Running

# starting string of "GOOD" vendor advisories
my @validreferences = (
	"https://curl.se/docs/CVE-",
	"https://www.openssl.org/news/secadv/",
	"https://xenbits.xen.org/xsa/advisory-",
	"https://www.intel.com/.*/intel-sa-",
        "https://developer.arm.com/.*/arm-security-updates/",
        "https://www.amd.com/.*/amd-sb-",
        "https://www.openssl.org/news/secadv/",
	"https://www.zerodayinitiative.com/advisories/",
	"https://www.postgresql.org/support/security/",
	"https://www.samba.org/samba/security/",
        'https://github.com/rancher/rancher/security/advisories',
        'https://github.com/rancher/rke2/security/advisories',
        'https://github.com/k3s-io/k3s/security/advisories',
        'https://github.com/squid-cache/squid/security/advisories/',
        'https://github.com/rancher-sandbox/rancher-desktop/security/advisories/',
        'https://github.com/neuvector/neuvector/security/advisories',
        'https://github.com/longhorn/security/advisories/',
        'https://github.com/longhorn/longhorn/security/advisories/',
	'https://github.com/distribution/distribution/security/advisories/',
);
foreach my $reference (@validreferences) {
	$reference =~ s/\//\\\//g;
}

my $validreferences = "(" . join("|",@validreferences) . ")";

%SMASHData::prod2cpe = (
	'openSUSE Leap 15.0' => 'cpe:/o:opensuse:leap:15.0',
	'openSUSE Leap 15.0 NonFree' => 'cpe:/o:opensuse:leap:15.0',
	'openSUSE Leap 15.1' => 'cpe:/o:opensuse:leap:15.1',
	'openSUSE Leap 15.1 NonFree' => 'cpe:/o:opensuse:leap:15.1',
	'openSUSE Leap 15.2' => 'cpe:/o:opensuse:leap:15.2',
	'openSUSE Leap 15.2 NonFree' => 'cpe:/o:opensuse:leap:15.2',
	'openSUSE Leap 15.3' => 'cpe:/o:opensuse:leap:15.3',
	'openSUSE Leap 15.3 SLE Imports' => 'cpe:/o:opensuse:leap:15.3',
	'openSUSE Leap 15.3 NonFree' => 'cpe:/o:opensuse:leap:15.3',
	'openSUSE Leap 15.4' => 'cpe:/o:opensuse:leap:15.4',
	'openSUSE Leap 15.4 SLE Imports' => 'cpe:/o:opensuse:leap:15.4',
	'openSUSE Leap 15.4 NonFree' => 'cpe:/o:opensuse:leap:15.4',
	'openSUSE Leap Micro 5.2' => 'cpe:/o:opensuse:leap-micro:5.2',
	#'openSUSE Leap Micro 5.3' => 'cpe:/o:opensuse:leap-micro:5.3',
	'openSUSE Tumbleweed' => 'cpe:/o:opensuse:tumbleweed',

	#'HPE Helion OpenStack 8' => 'cpe:/o:suse:hpe-helion-openstack:8',
	'HPE Helion OpenStack Cloud 8' => 'cpe:/o:suse:hpe-helion-openstack:8',
	'Subscription Management Tool 11 SP3' => 'cpe:/o:suse:smt:11:sp3',
	'SUSE Cloud 2.0' => 'cpe:/o:suse:cloud:2.0',
	'SUSE Cloud 3.0' => 'cpe:/o:suse:cloud:3.0',
	'SUSE Cloud 3.0' => 'cpe:/o:suse:cloud:3.0',
	'SUSE Cloud 4' => 'cpe:/o:suse:cloud:4',
	'SUSE Cloud 5' => 'cpe:/o:suse:cloud:5',
	'SUSE OpenStack Cloud 5' => 'cpe:/o:suse:cloud:5',
	'SUSE Cloud Compute Node for SUSE Linux Enterprise 12 5' => 'cpe:/o:suse:suse-sle12-cloud-compute:5',
	'SUSE Enterprise Storage 1.0' => 'cpe:/o:suse:ses:1.0',
	'SUSE Linux Enterprise Build System Kit 12' => 'cpe:/o:suse:sle-bsk:12',
	'SUSE Linux Enterprise Build System Kit 12 SP1' => 'cpe:/o:suse:sle-bsk:12:sp1',
	'SUSE Linux Enterprise Build System Kit 12 SP2' => 'cpe:/o:suse:sle-bsk:12:sp2',
	'SUSE Linux Enterprise Build System Kit 12 SP3' => 'cpe:/o:suse:sle-bsk:12:sp3',
	'SUSE Linux Enterprise Build System Kit 12 SP4' => 'cpe:/o:suse:sle-bsk:12:sp3',
	'SUSE Linux Enterprise Desktop 15' => 'cpe:/o:suse:sled:15',
	'SUSE Linux Enterprise Desktop 15 SP1' => 'cpe:/o:suse:sled:15:sp1',
	'SUSE Linux Enterprise Desktop 15 SP2' => 'cpe:/o:suse:sled:15:sp2',
	'SUSE Linux Enterprise Desktop 15 SP3' => 'cpe:/o:suse:sled:15:sp3',
	'SUSE Linux Enterprise Desktop 15 SP4' => 'cpe:/o:suse:sled:15:sp4',
	'SUSE Linux Enterprise High Availability 12' => 'cpe:/o:suse:sle-ha:12',
	'SUSE Linux Enterprise High Availability 12 SP1' => 'cpe:/o:suse:sle-ha:12:sp1',
	'SUSE Linux Enterprise High Availability 12 SP2' => 'cpe:/o:suse:sle-ha:12:sp2',
	'SUSE Linux Enterprise High Availability 12 SP3' => 'cpe:/o:suse:sle-ha:12:sp3',
	'SUSE Linux Enterprise High Availability 12 SP4' => 'cpe:/o:suse:sle-ha:12:sp4',
	'SUSE Linux Enterprise High Availability 12 SP5' => 'cpe:/o:suse:sle-ha:12:sp5',
	'SUSE Linux Enterprise High Availability 15' => 'cpe:/o:suse:sle-ha:15',
	'SUSE Linux Enterprise High Availability 15 SP1' => 'cpe:/o:suse:sle-ha:15:sp1',
	'SUSE Linux Enterprise High Availability 15 SP2' => 'cpe:/o:suse:sle-ha:15:sp2',
	'SUSE Linux Enterprise High Availability 15 SP3' => 'cpe:/o:suse:sle-ha:15:sp3',
	'SUSE Linux Enterprise High Availability 15 SP4' => 'cpe:/o:suse:sle-ha:15:sp4',
	'SUSE Linux Enterprise High Availability GEO 12 SP4' => 'cpe:/o:suse:sle-ha-geo:12:sp4',
	'SUSE Linux Enterprise High Availability GEO 12 SP5' => 'cpe:/o:suse:sle-ha-geo:12:sp5',
	'SUSE Linux Enterprise High Performance Computing 11 SP2' => 'cpe:/o:suse:sle_hpc:11:sp2',
	'SUSE Linux Enterprise High Performance Computing 11 SP3' => 'cpe:/o:suse:sle_hpc:11:sp3',
	'SUSE Linux Enterprise High Performance Computing 11 SP4' => 'cpe:/o:suse:sle_hpc:11:sp4',
	'SUSE Linux Enterprise High Performance Computing 12' => 'cpe:/o:suse:sle_hpc:12',
	'SUSE Linux Enterprise High Performance Computing 12 SP1' => 'cpe:/o:suse:sle_hpc:12:sp1',
	'SUSE Linux Enterprise High Performance Computing 15' => 'cpe:/o:suse:sle_hpc:15',
	'SUSE Linux Enterprise High Performance Computing 15-ESPOS' => 'cpe:/o:suse:sle_hpc-espos:15',
	#'SUSE Linux Enterprise High Performance Computing 15-LTSS' => 'cpe:/o:suse:sle_hpc-ltss:15',
	'SUSE Linux Enterprise High Performance Computing 15 SP1' => 'cpe:/o:suse:sle_hpc:15:sp1',
	#'SUSE Linux Enterprise High Performance Computing 15 SP1-ESPOS' => 'cpe:/o:suse:sle_hpc-espos:15:sp1',
	#'SUSE Linux Enterprise High Performance Computing 15 SP1-LTSS' => 'cpe:/o:suse:sle_hpc-ltss:15:sp1',
	'SUSE Linux Enterprise High Performance Computing 15 SP3' => 'cpe:/o:suse:sle_hpc:15:sp3',
	'SUSE Linux Enterprise High Performance Computing 15 SP4' => 'cpe:/o:suse:sle_hpc:15:sp4',
	'SUSE Linux Enterprise Module for CAP 15' => 'cpe:/o:suse:sle-module-cap-tools:15',
	'SUSE Linux Enterprise Module for CAP 15 SP1' => 'cpe:/o:suse:sle-module-cap-tools:15:sp1',
	'SUSE Linux Enterprise Module for CAP 15 SP2' => 'cpe:/o:suse:sle-module-cap-tools:15:sp2',
	'SUSE Linux Enterprise Module for CAP 15 SP3' => 'cpe:/o:suse:sle-module-cap-tools:15:sp3',
	'SUSE Linux Enterprise Module for High Performance Computing 12' => 'cpe:/o:suse:sle-module-hpc:12',
	'SUSE Linux Enterprise Module for High Performance Computing 15' => 'cpe:/o:suse:sle-module-hpc:15',
	'SUSE Linux Enterprise Module for High Performance Computing 15 SP1' => 'cpe:/o:suse:sle-module-hpc:15:sp1',
	'SUSE Linux Enterprise Module for High Performance Computing 15 SP2' => 'cpe:/o:suse:sle-module-hpc:15:sp2',
	'SUSE Linux Enterprise Module for High Performance Computing 15 SP3' => 'cpe:/o:suse:sle-module-hpc:15:sp3',
	'SUSE Linux Enterprise Module for High Performance Computing 15 SP4' => 'cpe:/o:suse:sle-module-hpc:15:sp4',
	'SUSE Linux Enterprise Module for HPC 12 SP2' => 'cpe:/o:suse:sle-module-hpc:12:sp2',	# does not really exists, but generated by smash for some reason
	'SUSE Linux Enterprise Module for Open Buildservice Development Tools 15' => 'cpe:/o:suse:sle-module-development-tools-obs:15',
	'SUSE Linux Enterprise Module for Open Buildservice Development Tools 15 SP1' => 'cpe:/o:suse:sle-module-development-tools-obs:15:sp1',
	'SUSE Linux Enterprise Module for Open Buildservice Development Tools 15 SP2' => 'cpe:/o:suse:sle-module-development-tools-obs:15:sp2',
	'SUSE Linux Enterprise Module for Package Hub 15' => 'cpe:/o:suse:packagehub:15',
	'SUSE Linux Enterprise Module for Package Hub 15 SP1' => 'cpe:/o:suse:packagehub:15:sp1',
	'SUSE Linux Enterprise Module for Package Hub 15 SP2' => 'cpe:/o:suse:packagehub:15:sp2',
	'SUSE Linux Enterprise Module for Package Hub 15 SP3' => 'cpe:/o:suse:packagehub:15:sp3',
	'SUSE Linux Enterprise Module for Package Hub 15 SP4' => 'cpe:/o:suse:packagehub:15:sp4',
	'SUSE Linux Enterprise Module for Realtime packages 15' => 'cpe:/o:suse:sle-module-rt:15',
	'SUSE Linux Enterprise Module for Realtime packages 15 SP1' => 'cpe:/o:suse:sle-module-rt:15:sp1',
	'SUSE Linux Enterprise Module for Realtime packages 15 SP2' => 'cpe:/o:suse:sle-module-rt:15:sp2',
	'SUSE Linux Enterprise Module for Realtime packages 15 SP3' => 'cpe:/o:suse:sle-module-rt:15:sp3',
	'SUSE Linux Enterprise Module for SUSE Manager Proxy 4.0' => 'cpe:/o:suse:sle-module-suse-manager-proxy:4.0',
	'SUSE Linux Enterprise Module for SUSE Manager Proxy 4.1' => 'cpe:/o:suse:sle-module-suse-manager-proxy:4.1',
	'SUSE Linux Enterprise Module for SUSE Manager Proxy 4.2' => 'cpe:/o:suse:sle-module-suse-manager-proxy:4.2',
	'SUSE Linux Enterprise Module for SUSE Manager Proxy 4.3' => 'cpe:/o:suse:sle-module-suse-manager-proxy:4.3',
	'SUSE Linux Enterprise Module for SUSE Manager Server 4.0' => 'cpe:/o:suse:sle-module-suse-manager-server:4.0',
	'SUSE Linux Enterprise Module for SUSE Manager Server 4.1' => 'cpe:/o:suse:sle-module-suse-manager-server:4.1',
	'SUSE Linux Enterprise Module for SUSE Manager Server 4.2' => 'cpe:/o:suse:sle-module-suse-manager-server:4.2',
	'SUSE Linux Enterprise Module for SUSE Manager Server 4.3' => 'cpe:/o:suse:sle-module-suse-manager-server:4.3',
	'SUSE Manager Server Module 4.0' => 'cpe:/o:suse:sle-module-suse-manager-server:4.3',
	'SUSE Manager Server Module 4.1' => 'cpe:/o:suse:sle-module-suse-manager-server:4.3',
	'SUSE Manager Server Module 4.2' => 'cpe:/o:suse:sle-module-suse-manager-server:4.3',
	'SUSE Manager Server Module 4.3' => 'cpe:/o:suse:sle-module-suse-manager-server:4.3',
	'SUSE Linux Enterprise Module for SAP Applications 15' => 'cpe:/o:suse:sle-module-sap-applications:15',
	'SUSE Linux Enterprise Module for SAP Applications 15 SP1' => 'cpe:/o:suse:sle-module-sap-applications:15:sp1',
	'SUSE Linux Enterprise Module for SAP Applications 15 SP2' => 'cpe:/o:suse:sle-module-sap-applications:15:sp2',
	'SUSE Linux Enterprise Module for SAP Applications 15 SP3' => 'cpe:/o:suse:sle-module-sap-applications:15:sp3',
	'SUSE Linux Enterprise Module for SAP Applications 15 SP4' => 'cpe:/o:suse:sle-module-sap-applications:15:sp4',

	'SUSE Linux Enterprise Point of Sale 11 SP2' => 'cpe:/o:suse:sle-pos:11:sp2',
	'SUSE Linux Enterprise Point of Sale 11 SP3' => 'cpe:/o:suse:sle-pos:11:sp3',
	'SUSE Linux Enterprise Point of Sale 11 SP3' => 'cpe:/o:suse:sle-pos:11:sp3',
	'SUSE Linux Enterprise Point of Sale 12 SP2-CLIENT' => 'cpe:/o:suse:sle-pos:12:sp2',
	'SUSE Linux Enterprise Point of Sale 12 SP2' => 'cpe:/o:suse:sle-pos:12:sp2',
	'SUSE Linux Enterprise Real Time 15 SP1' => 'cpe:/o:suse:sle_rt:15:sp1',
	#'SUSE Linux Enterprise Real Time 15 SP3' => 'cpe:/o:suse:sle_rt:15:sp3',
	'SUSE Linux Enterprise Real Time Extension 11 SP2' => 'cpe:/o:suse:suse-linux-enterprise-rt:11:sp2',
	'SUSE Linux Enterprise Real Time Extension 11 SP3' => 'cpe:/o:suse:suse-linux-enterprise-rt:11:sp3',	# synthesized
	'SUSE Linux Enterprise Real Time Extension 11 SP4' => 'cpe:/o:suse:suse-linux-enterprise-rt:11:sp4',	# synthesized
	'SUSE Linux Enterprise Real Time Extension 12 SP2' => 'cpe:/o:suse:suse-linux-enterprise-rt:12:sp2',
	'SUSE Linux Enterprise Real Time 12 SP2' => 'cpe:/o:suse:suse-linux-enterprise-rt:12:sp2',
	'SUSE Linux Enterprise Real Time Extension 12 SP3' => 'cpe:/o:suse:suse-linux-enterprise-rt:12:sp3',
	'SUSE Linux Enterprise Real Time 12 SP3' => 'cpe:/o:suse:suse-linux-enterprise-rt:12:sp3',
	'SUSE Linux Enterprise Real Time Extension 12 SP4' => 'cpe:/o:suse:suse-linux-enterprise-rt:12:sp4',
	'SUSE Linux Enterprise Real Time Extension 12 SP5' => 'cpe:/o:suse:suse-linux-enterprise-rt:12:sp5',
	'SUSE Linux Enterprise Server 11 SP1-CLIENT-TOOLS' => 'cpe:/a:suse:sle-clienttools:11:sp1',
	'SUSE Linux Enterprise Server 11 SP1-TERADATA' => 'cpe:/o:suse:sles:11:sp1:teradata',
	'SUSE Linux Enterprise Server 11 SP3-CLIENT-TOOLS' => 'cpe:/a:suse:sle-clienttools:11:sp3',
	'SUSE Linux Enterprise Server 11 SP3-TERADATA' => 'cpe:/o:suse:sles:11:sp3:teradata',
	'SUSE Linux Enterprise Server 11 SP4-CLIENT-TOOLS' => 'cpe:/a:suse:sle-clienttools:11:sp4',
	'SUSE Linux Enterprise Server 11 SP4' => 'cpe:/o:suse:suse_sles:11:sp4',
	#'SUSE Linux Enterprise Server 12 SP2-BCL' => 'cpe:/o:suse:sles-bcl:12:sp2',
	'SUSE Linux Enterprise Server 12 SP2-LTSS-ERICSSON' => 'cpe:/o:suse:sles-ltss:12:sp2',
	'SUSE Linux Enterprise Server 12 SP2-LTSS-SAP' => 'cpe:/o:suse:sles-ltss:12:sp2',


	#'SUSE Linux Enterprise Server 12 SP3-BCL' => 'cpe:/o:suse:sles-bcl:12:sp3',
	'SUSE Linux Enterprise Server 12 SP3-TERADATA' => 'cpe:/o:suse:sles_teradata:12:sp3',
	'SUSE Linux Enterprise Server 12 SP3-LTSS-TERADATA' => 'cpe:/o:suse:sles_teradata:12:sp3-ltss',
	'SUSE Linux Enterprise Server 15 SP1-BCL' => 'cpe:/o:suse:sles_bcl:15:sp1',
	'SUSE Linux Enterprise Server 15 SP2-BCL' => 'cpe:/o:suse:sles_bcl:15:sp2',
	'SUSE Linux Enterprise Server for Raspberry Pi 12 SP2' => 'cpe:/o:suse:sles:12:sp2',
	'SUSE Linux Enterprise Server for SAP Applications 11' => 'cpe:/o:suse:sles_sap:11',
	'SUSE Linux Enterprise Server for SAP Applications 11 SP1' => 'cpe:/o:suse:sles_sap:11:sp1',
	'SUSE Linux Enterprise Server for SAP Applications 11 SP2' => 'cpe:/o:suse:sles_sap:11:sp2',
	'SUSE Linux Enterprise Server for SAP Applications 11 SP3' => 'cpe:/o:suse:sles_sap:11:sp3',
	'SUSE Linux Enterprise Server for SAP Applications 11 SP4' => 'cpe:/o:suse:sles_sap:11:sp4',
	'SUSE Linux Enterprise Server for VMWare 11 SP2' => 'cpe:/o:suse:sles:11:sp2:vmware',
	'SUSE Linux Enterprise Server for VMWare 11 SP3' => 'cpe:/o:suse:sles:11:sp3:vmware',
	'SUSE Manager 1.7' => 'cpe:/o:suse:suse-manager-server:1.7',
	'SUSE Manager 2.1' => 'cpe:/o:suse:suse-manager-server:2.1',
	'SUSE Manager Proxy 4.3' => 'cpe:/o:suse:suse-manager-proxy:4.3',
	'SUSE Manager Retail Branch Server 4.3' => 'cpe:/o:suse:suse-manager-retail-branch-server:4.3',
	'SUSE Manager Server 4.3' => 'cpe:/o:suse:suse-manager-server:4.3',
	'SUSE Manager Tools 12-BETA' => 'cpe:/o:suse:sle-manager-tools:12',
	'SUSE Manager Tools 12' => 'cpe:/o:suse:sle-manager-tools:12',
	'SUSE Manager Tools 15-BETA' => 'cpe:/o:suse:sle-manager-tools:15',
	'SUSE Manager Tools 15' => 'cpe:/o:suse:sle-manager-tools:15',
	'SUSE Manager Tools 15 SP1' => 'cpe:/o:suse:sle-manager-tools:15:sp1',
	'SUSE MicroOS 5.0' => 'cpe:/o:suse:suse-microos:5.0',
	'SUSE OpenStack Cloud 4' => 'cpe:/o:suse:cloud:4',
	'SUSE Package Hub 12' => 'cpe:/o:suse:packagehub:12',
	'SUSE Package Hub 12 SP1' => 'cpe:/o:suse:packagehub:12:sp1',
	'SUSE Package Hub 12 SP2' => 'cpe:/o:suse:packagehub:12:sp2',
	'SUSE Package Hub 12 SP3' => 'cpe:/o:suse:packagehub:12:sp3',
	'SUSE Package Hub 12 SP4' => 'cpe:/o:suse:packagehub:12:sp4',
	'SUSE Package Hub 12 SP5' => 'cpe:/o:suse:packagehub:12:sp5',
	'SUSE Studio Onsite Runner 1.2' => 'cpe:/o:suse:suse-studio-onsite-runner:1.2',
	'SUSE WebYast 1.3' => 'cpe:/o:suse:webyast:1.3',

	# synthesized
	'SUSE Linux Enterprise Server 11-SECURITY' => 'cpe:/o:suse:sles:11:security',

# delete once we have 15 sp3 ready
	'SUSE Linux Enterprise Server 15 SP4' => 'cpe:/o:suse:sles:15:sp4',
	#'SUSE Linux Enterprise Server for SAP Applications 15 SP3' => 'cpe:/o:suse:sles_sap:15:sp3',
	'SUSE Linux Enterprise Server for SAP Applications 15 SP4' => 'cpe:/o:suse:sles_sap:15:sp4',
	'SUSE Linux Enterprise Module for Open Buildservice Development Tools 15 SP3' => 'cpe:/o:suse:sle-module-development-tools-obs:15:sp3',
	'SUSE Linux Enterprise Module for Open Buildservice Development Tools 15 SP4' => 'cpe:/o:suse:sle-module-development-tools-obs:15:sp4',
	'SUSE Linux Enterprise Module for Web Scripting 15 SP3' => 'cpe:/o:suse:sle-module-web-scripting:15:sp3',
	'SUSE Linux Enterprise Server 15 SP3-LTSS' => 'cpe:/o:suse:sles-ltss:15:sp3',

	'SUSE Liberty Linux 9' => 'cpe:/o:suse:sll:9',
	'SUSE Liberty Linux 8' => 'cpe:/o:suse:sll:8',
	'SUSE Liberty Linux 7' => 'cpe:/o:suse:sll:7',
);

my %cnamap = (
	"134c704f-9b21-4f2e-91b3-4a467353bcc0"	=> "CISA-ADP",
	"secalert\@redhat.com"			=> "Red Hat",
	"zdi-disclosures\@trendmicro.com"	=> "ZDI",
	"secalert_us\@oracle.com"		=> "Oracle",
	"security\@open-xchange.com"		=> "Open-Xchange",
	"secure\@intel.com"			=> "Intel",
	"talos-cna\@cisco.com"			=> "Talos",
	"ykramarz\@cisco.com"			=> "CISCO",
	"cve\@gitlab.com"			=> "Gitlab",
	"psirt\@us.ibm.com"			=> "IBM",
	"f86ef6dc-4d3a-42ad-8f28-e6d5547a5007"	=> "PostgreSQL",
	"security\@documentfoundation.org"	=> "The Document Foundation",
	"cna\@vuldb.com"			=> "VulDB",
	"security-advisories\@github.com"	=> "GitHub",
	"jordan\@liggitt.net"			=> "Kubernetes",
	"cna\@mongodb.com"			=> "MongoDB",
	"security\@ubuntu.com"			=> "Canonical",
	"meissner\@suse.de"			=> "SUSE",
	"security\@tcpdump.org"			=> "Tcpdump Group",
	"security\@grafana.com"			=> "Grafana Labs",
	"cve-coordination\@google.com"		=> "Google Inc",
	"support\@hackerone.com"		=> "HackerOne",
	"cve\@mitre.org"			=> "MITRE",
	"secure\@microsoft.com"			=> "Microsoft",
	"patrick\@puiterwijk.org"		=> "Fedora Project",
	"psirt\@nvidia.com"			=> "NVIDIA Corporation",
	"security\@hashicorp.com"		=> "HashiCorp",
	"infosec\@edk2.groups.io"		=> "TianoCore.org",
	"bressers\@elastic.co"			=> "Elastic",
	"security\@apache.org"			=> "Apache Software Foundation",
	"sep\@nlnetlabs.nl"			=> "NLnet Labs",
);

sub
map_cna($) {
	my ($cnaid) = @_;
	if (defined($cnamap{$cnaid})) {
		return $cnamap{$cnaid};
	}
	return $cnaid;
}

%SMASHData::cpe2prod = ();

my %prod2cpestatic = %SMASHData::prod2cpe;

foreach my $cpe (keys %SMASHData::prod2cpe)  {
	$SMASHData::cpe2prod{$SMASHData::prod2cpe{$cpe}} = $cpe;
}


sub
get_cpe($) {
	my ($product) = @_;

	# $product =~ s/Web Scripting/Web and Scripting/;

	if (defined($SMASHData::prod2cpe{$product})) {
		return $SMASHData::prod2cpe{$product};
	}
	if ($product =~ /-LTSS/) {
		$product =~ s/-LTSS/ LTSS/;
		if (defined($SMASHData::prod2cpe{$product})) {
			return $SMASHData::prod2cpe{$product};
		}
	}
	if ($product =~ /-ESPOS/) {
		$product =~ s/-ESPOS/ ESPOS/;
		if (defined($SMASHData::prod2cpe{$product})) {
			return $SMASHData::prod2cpe{$product};
		}
	}
	$product =~ s/ for \S*$//;	# filter the for x86_64
	if (defined($SMASHData::prod2cpe{$product})) {
		return $SMASHData::prod2cpe{$product};
	}
	return undef;
}

%SMASHData::cvss = ();
%SMASHData::cvssv3 = ();
%SMASHData::cvssv4 = ();
%SMASHData::severity = ();
%SMASHData::state = ();
%SMASHData::embargoedcves = ();

# timestamps CVE -> { "tag" -> stamp }
#     "creation_date": "2020-06-15T21:34:14.547958+02:00",
#     "modified_date": "2022-08-29T11:00:53.283935+02:00",
#     "ts_ignore": null,
#     "ts_analysis": "2020-06-16T10:14:27.481398+02:00",
#     "ts_pending": "2020-06-17T14:41:38.499087+02:00",
#     "ts_running": "2022-08-29T11:00:35.786248+02:00",
#     "ts_resolved": null,
#     "ts_deleted": null,
%SMASHData::timestamps = ();

# { CVE -> { ID -> URL }}
%SMASHData::references = ();

# { CVE -> { PROD -> { PKG -> STATE } } }
%SMASHData::pkgstate = ();
%SMASHData::codestreampkgstate = ();

# { CVE -> vendoradvisory }
%SMASHData::vendoradvisories = ();

# { CVE -> 1 }
%SMASHData::errorcves = ();

my %loadedissue = ();

my $smashhostbase = "https://smash.suse.de/";

# http://10.162.168.43:8000/api/issues/security-with-cves/

# new stuff from victor
# curl -L  -H "Accept: application/json" https://smash.suse.de/issue/pending-security

# CVSS scores
# https://smash.suse.de/references/cves/

sub remap_name($$$) {
	my ($xname, $codename, $version) = @_;


	if ($xname =~ /^SUSE Package Hub/) {
		$version =~ s/-SP/ SP/;
		# print STDERR "map phub from $xname / $codename / $version  to SUSE Linux Enterprise Module for Package Hub $version\n";
		return "SUSE Linux Enterprise Module for Package Hub $version";
	}

	# SL Micro 6.0 confusion
	if ($xname eq "SUSE Linux Micro") {
		return "SUSE Linux Enterprise Micro $version";
	}

	if ($xname =~ /^SUSE/ || $xname =~ /^HPE/ || $xname =~ /SLES/ || $xname =~ /Magnum/) {
		if ($xname !~ /[0-9]/) {
			if (!defined($version)) {
				if ($codename eq "sle-manager-tools-15-SP1") { # hack until fixed
					$version = "15-SP1";
				} else {
					print STDERR "xname $xname, codename $codename has undef version.\n"
				}
			}
			$version =~ s/-SP/ SP/;
			if ($xname =~ /(.*) ESPOS/) { return "$1 $version-ESPOS"; }
			if ($xname =~ /(.*) LTSS/) { return "$1 $version-LTSS"; }
			if ($xname =~ /(.*) BCL/) { return "$1 $version-BCL"; }
			if (($xname eq "SUSE Linux Enterprise Server") && ($version eq "11 SP4")) {	# all SMASH 11 SP4 are now actually 11 SP4 LTSS
				$version .= "-LTSS";
			}
			return "$xname $version";
		}
		return $xname;
	}
	if ($xname eq "") {
		return $codename if ($codename =~ /^openSUSE/);
		return $codename if ($codename =~ /^SLE/);
		#die "empty xname, codename $codename, version $version\n";
	}

	if ($xname =~ /^(.*) Module$/) {
		my $module = $1;

		if (	($codename =~ /-(\d*)$/ ) 		||
			($codename =~ /-(\d*-SP\d)$/ )
		) {
			my $ver = $1;

			$ver =~ s/-/ /;	# 15-sp1 -> 15 sp1
			return "SUSE Linux Enterprise Module for $module $ver";
		}

		if (defined($version)) {
			$version =~ s/-/ /;
			return "SUSE Linux Enterprise Module for $module $version";
		}

		print STDERR "module $xname / $codename not mapped\n";
	}
	if ($xname eq "openSUSE Leap") {
		return "$xname $version";
	}
	if ($xname eq "openSUSE Leap Micro") {
		return "$xname $version";
	}
	# catch all
	return $xname;
}

sub rename_smash_name($) {
	my ($name) = @_;

	my $major;
	my $sp;

	$sp = "FIXMEsp $name";
	$major = "FIXMEmajor $name";
	if ($name =~ /(\d\d*)-(SP\d)$/) {
		$major = $1;
		$sp = $2;
	} else {
		if ($name =~ /-([\d.]*)$/) {
			$major = $1;
			$sp = "GA";
		} else {
			if ($name eq "SLE-10-SP3-MANAGER") {
				$major = "10";
				$sp = "SP3";
			}
		}
	}
	if ($name =~ /CAASP-/i) { return "CaaS Platform $major"; }
	if ($name =~ /SLES_TERADATA-\d/) { return "SUSE Linux Enterprise Server for Teradata $major $sp"; }
	if ($name =~ /SLES_LTSS-\d/) { return "SUSE Linux Enterprise Server $major $sp-LTSS"; }
	if ($name =~ /SLES-LTSS-\d/) { return "SUSE Linux Enterprise Server $major $sp-LTSS"; }
	if ($name =~ /SLES_RPI-\d/) { return "SUSE Linux Enterprise Server $major $sp for Raspberry PI"; }
	if ($name =~ /SLED-\d/) { return "SUSE Linux Enterprise Desktop $major $sp"; }
	if ($name =~ /SLE-10-SP3-MANAGER/) { return "SUSE Linux Enterprise Tools for SUSE Manager $major $sp"; }
	if ($name =~ /SLE-\d/) { return "SUSE Linux Enterprise $major $sp"; }
	if ($name =~ /SLES-\d/) { return "SUSE Linux Enterprise Server $major $sp"; }
	if ($name =~ /SLES_RPI-\d/) { return "SUSE Linux Enterprise Server $major $sp for Raspberry Pi"; }
	if ($name =~ /SUSE-Linux-Enterprise-RT-\d/) { return "SUSE Linux Enterprise Server Realtime $major $sp"; }
	if ($name =~ /SLES-for-VMware-\d/) { return "SUSE Linux Enterprise Server for VMWare $major $sp"; }
	if ($name =~ /SLES_SAP-\d/) { return "SUSE Linux Enterprise Server for SAP Applications $major $sp"; }
	if ($name =~ /sap-aio-\d/) { return "SUSE Linux Enterprise Server for SAP AIO $major $sp"; }
	if ($name =~ /sap-es-\d/) { return "SUSE Linux Enterprise Server for SAP ES $major $sp"; }
	if ($name =~ /sle-ha-\d/) { return "SUSE Linux Enterprise High Availability Extension $major $sp"; }
	if ($name =~ /sle-hae-\d/) { return "SUSE Linux Enterprise High Availability Extension $major $sp"; }
	if ($name =~ /sle-sdk-\d/) { return "SUSE Linux Enterprise SDK $major $sp"; }
	if ($name =~ /sle-we-\d/) { return "SUSE Linux Enterprise Workstation Extension $major $sp"; }
	if ($name =~ /sle-bsk-\d/) { return "SUSE Linux Enterprise BSK $major $sp"; }
	if ($name =~ /sle-pos-\d/) { return "SUSE Linux Enterprise Point of Sale $major $sp"; }
	if ($name =~ /sle-security-/) { return "SUSE Linux Enterprise Server 11-SECURITY"; } # name similar to YUM output "SUSE Linux Enterprise Server 11-SECURITY"
	if ($name =~ /sle-clienttools-/) { return "SUSE Linux Enterprise Client Tools for SUSE Manager $major $sp"; }
	if ($name =~ /sle-manager-tools-/) { return "SUSE Linux Enterprise Client Tools for SUSE Manager $major $sp"; }
	if ($name =~ /sle-module-suse-manager-proxy-/) { return "SUSE Manager Proxy $major Module"; }
	if ($name =~ /sle-module-suse-manager-server-/) { return "SUSE Manager Server $major Module"; }
	if ($name =~ /suse-openstack-cloud-/) { return "SUSE OpenStack Cloud $major"; }
	if ($name =~ /suse-cloud-/) { return "SUSE Cloud $major"; }
	if ($name =~ /suse-sle12-cloud-compute-/) { return "SUSE Linux Enterprise 12 Compute Node for Cloud $major"; }
	if ($name =~ /suse-cloud-deps-/) { return "SUSE Cloud $major"; }
	if ($name =~ /ses-/) { return "SUSE Storage $major"; }
	if ($name =~ /SUSE-Manager-Proxy-\d/) { return "SUSE Manager Proxy $major"; }
	if ($name =~ /SUSE-Manager-Server-\d/) { return "SUSE Manager Server $major"; }
	if ($name =~ /suse-manager-retail-\d/) { return "SUSE Manager Retail $major"; }
	if ($name =~ /sle-slms-\d/) { return "SUSE Lifecycle Management Server $major"; }
	if ($name =~ /sle-studioonsite-\d/) { return "SUSE Studio Onsite $major"; }
	if ($name =~ /sle-studioonsiterunner-\d/) { return "SUSE Studio Onsite Runner $major"; }
	if ($name =~ /sle-smt-/) { return "SUSE Subscription Management Tool $major"; }
	if ($name =~ /sle-module-web-scripting-/) { return "SUSE Linux Enterprise Module for Web and Scripting $major"; }
	if ($name =~ /sle-module-public-cloud-/) { return "SUSE Linux Enterprise Module for Public Cloud $major"; }
	if ($name =~ /sle-pubcloud-/) { return "SUSE Linux Enterprise Module for Public Cloud $major"; }
	if ($name =~ /sle-module-adv-systems-management-/) { return "SUSE Linux Enterprise Module for Advanced Systems Management $major"; }
	if ($name =~ /sle-module-basesystem-/) { return "SUSE Linux Enterprise Module for Basesystem $major $sp"; }
	if ($name =~ /sle-module-containers-/) { return "SUSE Linux Enterprise Module for Containers $major"; }
	if ($name =~ /sle-module-desktop-applications-/) { return "SUSE Linux Enterprise Module for Desktop Applications $major $sp"; }
	if ($name =~ /sle-module-sap-applications-/) { return "SUSE Linux Enterprise Module for SAP Applications $major $sp"; }
	if ($name =~ /sle-module-development-tools-/) { return "SUSE Linux Enterprise Module for Development Tools $major $sp"; }
	if ($name =~ /sle-module-server-applications-/) { return "SUSE Linux Enterprise Module for Server Applications $major $sp"; }
	if ($name =~ /sle-module-legacy-/) { return "SUSE Linux Enterprise Module for Legacy $major"; }
	if ($name =~ /sle-module-hpc-/) { return "SUSE Linux Enterprise Module for High Performance Computing $major"; }
	if ($name =~ /sle-module-toolchain-/) { return "SUSE Linux Enterprise Module for Toolchain $major"; }
	if ($name =~ /sle-module-cap-tools-/) { return "SUSE Linux Enterprise Module for CAP $major"; }
	if ($name =~ /sle-live-patching-/) { return "SUSE Linux Enterprise Live Patching$major"; }
	if ($name =~ /sle-module-live-patching-/) { return "SUSE Linux Enterprise Live Patching$major"; }
	if ($name =~ /openstack-cloud-magnum-orchestration/) { return "OpenStack Cloud Magnum Orchestration $major"; }
	if ($name =~ /sle-11-WebYaST/) { return "WebYaST $major"; }
	if ($name =~ /openSUSE/) { return "openSUSE $major"; }
	if ($name =~ /hpe-helion-openstack/) { return "HPE Helion OpenStack $major"; }
	if ($name =~ /hpe-helion-openstack-cloud/) { return "HPE Helion OpenStack Cloud $major"; }
	if ($name =~ /SLE-HPC/) { return "SUSE Linux Enterprise High Performance Computing $major"; }
	if ($name =~ /SLE_HPC-ESPOS/) { return "SUSE Linux Enterprise High Performance Computing ESPOS $major $sp"; }
	if ($name =~ /SLE_HPC-LTSS/) { return "SUSE Linux Enterprise High Performance Computing LTSS $major $sp"; }
	if ($name =~ /SLES-BCL/) { return "SUSE Business Critical Linux $major $sp"; }
	if ($name =~ /sle-module-python2/) { return "SUSE Linux Enterprise Module for Python 2 $major $sp"; }
	if ($name =~ /OES-/) { return "Open Enterprise Server $major $sp"; }

	print STDERR "$name is not mapped yet.\n";
	return $name;
}


sub
read_embargoed_bugs() {
	my $url = "$smashhostbase/api/embargoed-bugs/";

	my $json = "";
	my $mapref;

	$json = get_url($url);

	eval {
		$mapref = decode_json($json);
	} or do {
		die "json invalid: $json\n";
	};
	my @embargoed = @{$mapref};
	foreach my $embargoed (@embargoed) {
		my @cves = @{$embargoed->{'cves'}};
		foreach my $cve (@cves) {
			# print STDERR Dumper(\$cve);
			$SMASHData::embargoedcves{$cve->{name}} = 1;
		}
	}
	# print STDERR Dumper(\%SMASHData::embargoedcves);
}

sub
read_smash_issue($$) {
	my ($cve,$force) = @_;
	my $url = "$smashhostbase/api/issues/?category=security&reference=$cve";
	my %map;
	my $urlindex = 0;


	############ JSON loader code, with caching ###############

	return if (!$force && defined($loadedissue{$cve}));

	$loadedissue{$cve} = 1;


	my $blocks = 0;

	do {
		my $json = "";
		my $mapref;

		if (!$force && open(SMASHISSUE,"$cverepobase/smash/issue2/$cve.$urlindex")) {
			$json = <SMASHISSUE>;
			close(SMASHISSUE);

			%map = ();
			eval {
				$mapref = decode_json($json);
				%map = %{$mapref};
			} or do {
				warn "json invalid: $json\n";
				unlink("$cverepobase/smash/issue2/$cve.$urlindex");
				$json = "";
			};


			# Invalid json saved?
			if (!defined($map{'count'})) {
				$json = "";
			}
#			my $age = -M "$cverepobase/smash/issue/$cve.$urlindex";
#			if ($age < 2) {
#				$json = "";
#				print STDERR "refetching $cve\n";
#			}

		}

		if ($json eq "") {
			$json = get_url($url);
			open(SMASHISSUE,">$cverepobase/smash/issue2/$cve.$urlindex.new")||die "smash/issue2/$cve.$urlindex.new:$!";
			print SMASHISSUE "$json\n";
			close(SMASHISSUE);

			my $oldjson = "";
			if (open(OLDSMASHISSUE,"<$cverepobase/smash/issue2/$cve.$urlindex")) {
				$oldjson = join("",<OLDSMASHISSUE>);
				close(OLDSMASHISSUE);
			}

			if ($oldjson ne $json) {
				print STDERR "changed $cve.$urlindex\n" if -t STDERR;
				if (-t STDERR) {
					system("jq . <$cverepobase/smash/issue2/$cve.$urlindex  >before; jq . <$cverepobase/smash/issue2/$cve.$urlindex.new  >after; diff -u before after ; rm before after");
				}
				unlink("$cverepobase/smash/issue2/$cve.$urlindex");
				rename("$cverepobase/smash/issue2/$cve.$urlindex.new", "$cverepobase/smash/issue2/$cve.$urlindex")||die "rename $cverepobase/smash/issue2/$cve.$urlindex.new:$!";
			} else {
				print STDERR "not changed $cve.$urlindex\n" if -t STDERR;
				unlink("$cverepobase/smash/issue2/$cve.$urlindex.new");
			}

			eval {
				$mapref = decode_json($json);
			} or do {
				warn "json invalid: $json\n";
				unlink("$cverepobase/smash/issue2/$cve.$urlindex");
				return;
			};
		}
		$urlindex++;

		%map = %{$mapref};

		############ Here the processing begin ###############

		my @results = @{$map{'results'}};
		foreach my $result (@results) {
			if ($result->{'state'} eq "Deleted") {
				# print STDERR "skipping deleted.\n";
				next;
			}
			$blocks++;
			#print STDERR "==== state = " . $result->{'state'}  . "\n";
			#print STDERR Dumper($result);

			if ($result->{'name'} =~ /^bnc#(\d*)/) {
				$SMASHData::references{$cve}->{$result->{'name'}} = "https://bugzilla.suse.com/$1";
			}

			$SMASHData::references{$cve}->{"SMASH Issue ".$result->{'id'}} = "https://smash.suse.de/issue/" . $result->{'id'} . "/";

			foreach my $reference (@{$result->{'references'}}) {
				# we export only the JIRA and Bugzillas currently
				#if ($reference->{url} =~ /jira.suse.com/) {
				#	$SMASHData::references{$cve}->{$reference->{'name'}} = $reference->{url};
				#}
				#if ($reference->{url} =~ /bugzilla.suse.com/) {
				#	$SMASHData::references{$cve}->{$reference->{'name'}} = $reference->{url};
				#}

				# export all references now, for embargo detection

				$SMASHData::references{$cve}->{$reference->{'name'}} = $reference->{url};

				if ($reference->{url} =~ /$validreferences/) {
					$SMASHData::vendoradvisories{$cve}->{$reference->{'name'}} = $reference->{url};
				}

				# CHECK: export more?
				# print STDERR Dumper($reference) if -t STDERR;
			}


			# do not import package relations from the Merged marked issue, but use the CVSS score.
			if ($result->{'state'} ne "Merged") {
				if (defined($SMASHData::state{$cve})) {
					if ( $SMASHData::state{$cve} ne $SMASHData::state{$cve}) {
						print STDERR "$cve state changed ... $SMASHData::state{$cve} vs $SMASHData::state{$cve}\n";
					}
				}
				$SMASHData::state{$cve}		= $result->{'state'};
				$SMASHData::severity{$cve}	= $result->{'severity'};


				$SMASHData::timestamps{$cve}->{"created"} = str2time($result->{'creation_date'});
				$SMASHData::timestamps{$cve}->{"modified"} = str2time($result->{'modified_date'});
				if ($result->{'ts_ignore'})	{ $SMASHData::timestamps{$cve}->{"ignored"}	= str2time($result->{'ts_ignore'}); }
				if ($result->{'ts_analysis'})	{ $SMASHData::timestamps{$cve}->{"analysis"}	= str2time($result->{'ts_analysis'}); }
				if ($result->{'ts_pending'})	{ $SMASHData::timestamps{$cve}->{"pending"}	= str2time($result->{'ts_pending'}); }
				if ($result->{'ts_running'})	{ $SMASHData::timestamps{$cve}->{"running"}	= str2time($result->{'ts_running'}); }
				if ($result->{'ts_resolved'})	{ $SMASHData::timestamps{$cve}->{"resolved"}	= str2time($result->{'ts_resolved'}); }

				# read_affected_software($result->{'id'},$cve,$force);
				my @affected = @{$result->{'affected_packages'}};

				foreach my $package (@affected) {
					#        {
					#          "package": "xorg-x11-server",
					#          "codestream": null,
					#          "product": {
					#            "cpe": "cpe:/o:suse:sles-bcl:12:sp3",
					#            "summary": "SUSE Linux Enterprise Server 12 SP3 BCL",
					#            "version": "12-SP3",
					#            "name": "SLES-BCL"
					#          },
					#          "relation": "Released",
					#          "id": 1325855
					#        },
					#print STDERR Dumper($package);

					my $prod;
					if (defined($package->{'product'})) {
						my $product = $package->{'product'};
						#print STDERR Dumper($package->{'product'});
						$prod = $product->{'summary'};
						$prod = remap_name($prod, $product->{'name'},$product->{'version'});
						if (defined($product->{'cpe'})) {
							$SMASHData::prod2cpe{$prod} = $product->{'cpe'};
							$SMASHData::cpe2prod{$product->{'cpe'}} = $prod;

							if (defined($prod2cpestatic{$prod})) {
								print STDERR "got $prod / " . $product->{'cpe'} . " which is in static list\n" if -t STDERR;
							}
						}
						# we have the right name in $prod!
						# { CVE -> { PROD -> { PKG -> STATE } } }

						if (defined($SMASHData::pkgstate{$cve}->{$prod}->{$package->{'package'}})) {
							if ($SMASHData::pkgstate{$cve}->{$prod}->{$package->{'package'}} ne $package->{'relation'}) {
								$SMASHData::errorcves{$cve} = 1;
							}
						}
						$SMASHData::pkgstate{$cve}->{$prod}->{$package->{'package'}} = $package->{'relation'};
						# hack for kernel
						if ($package->{'package'} eq "kernel-source") {
							$SMASHData::pkgstate{$cve}->{$prod}->{'kernel-default'} = $package->{'relation'};
						}
					} else {
						$prod = $package->{'codestream'};
						$SMASHData::codestreampkgstate{$cve}->{$prod}->{$package->{'package'}} = $package->{'relation'};
						if ($package->{'package'} eq "kernel-source") {
							if ($prod eq "SUSE:SLE-15-SP1:Update") {
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.0"}->{'kernel-default'} = $package->{'relation'};
							}
							if ($prod eq "SUSE:SLE-15-SP3:Update") {
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.1"}->{'kernel-default'} = $package->{'relation'};
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.2"}->{'kernel-default'} = $package->{'relation'};
							}
							if ($prod eq "SUSE:SLE-15-SP4:Update") {
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.3"}->{'kernel-default'} = $package->{'relation'};
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.4"}->{'kernel-default'} = $package->{'relation'};
							}
						}
						if ($package->{'package'} eq "kernel-source-rt") {
							if ($prod eq "SUSE:SLE-15-SP1:Update") {
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.0"}->{'kernel-rt'} = $package->{'relation'};
							}
							if ($prod eq "SUSE:SLE-15-SP3:Update:Products:SLERT:Update") {
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.1"}->{'kernel-rt'} = $package->{'relation'};
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.2"}->{'kernel-rt'} = $package->{'relation'};
							}
							if ($prod eq "SUSE:SLE-15-SP4:Update:Products:SLERT:Update") {
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.3"}->{'kernel-rt'} = $package->{'relation'};
								$SMASHData::pkgstate{$cve}->{"SUSE Linux Enterprise Micro 5.4"}->{'kernel-rt'} = $package->{'relation'};
							}
						}
					}
				}
			}

			# cvss v2 v3
			my $cvssref = $result->{'cvss'};
			foreach my $cvssentry (@{$cvssref}) {
				my %cvssentry = %{$cvssentry};

				if (!defined($cvssentry{'reference'})) {
					# rare buggy case
					next;
				}
				if ($cvssentry{'source'} eq 'NVD') {
					$cvssentry{'source'} = 'National Vulnerability Database';
					if ($cvssentry{'rating_agency'} ne "") {
						$cvssentry{'source'} = "CNA (" . &map_cna($cvssentry{'rating_agency'}) . ")";
					}
				}

				my $cve = $cvssentry{'reference'};

				#print Dumper(\$cvssentry);
				# {
				# 'vector' => 'AV:N/AC:H/Au:N/C:P/I:P/A:N',
				# 'source' => 'SUSE',
				# 'reference' => 'bnc#938913',
				# 'id' => 90054,
				# 'description' => '',
				# 'creation_date' => '2016-02-03T09:33:35.725723Z',
				# 'score' => '4',
				# 'reference_url' => 'https://smash.suse.de/api/reference-detail/90054'
				# },


				my $sources = ();

				if (!defined($cvssentry{'version'})) {
					print STDERR "$cve has no version entry?\n";
					next;
				}

				if ($cvssentry{'version'} eq "2") {
					if (defined($SMASHData::cvss{$cve})) {
						$sources = $SMASHData::cvss{$cve};
					}
				}
				if ($cvssentry{'version'} =~/^3/) {
					if (defined($SMASHData::cvssv3{$cve})) {
						$sources = $SMASHData::cvssv3{$cve};
					}
				}
				if ($cvssentry{'version'} =~/^4/) {
					if (defined($SMASHData::cvssv4{$cve})) {
						$sources = $SMASHData::cvssv4{$cve};
					}
				}

				$sources->{$cvssentry{'source'}}->{"created"} = str2time($cvssentry{'creation_date'});
				$sources->{$cvssentry{'source'}}->{"modified"} = str2time($cvssentry{'modified_date'});
				$sources->{$cvssentry{'source'}}->{"base_vector"} = $cvssentry{'vector'};
				$sources->{$cvssentry{'source'}}->{"base_score"} = $cvssentry{'score'};
				$sources->{$cvssentry{'source'}}->{"version"} = $cvssentry{'version'};

				if ($cvssentry{'version'} eq "2") {
					$SMASHData::cvss{$cve} = $sources;
				}
				if ($cvssentry{'version'} =~/^3/) {
					$SMASHData::cvssv3{$cve} = $sources;
				}
				if ($cvssentry{'version'} =~/^4/) {
					$SMASHData::cvssv4{$cve} = $sources;
				}

			}
		}
		# this will either be a query or urlindex+=1 fetch from the cache
		$url = $map{'next'};
	} while (defined($map{'next'}));
	if (-t STDERR && ($blocks > 1)) {
		print STDERR "$cve has more than one SMASH issue\n";
	}
}

# Idea is to fetch issues and find CVE <-> BNC aliases
sub
fetch_last_smash_issues() {
	my $url = "$smashhostbase/api/issues/?category=security&ordering=-creation_date";
	my %map;
	my $urlindex = 0;
	my %cvemap = ();
	my %embargo = ();
	my $last = 0;

	############ JSON loader code, with caching ###############

	do {
		my $json = "";
		my $mapref;

		print STDERR "getting $url\n" if -t STDERR;

		$json = get_url($url);

		eval {
			$mapref = decode_json($json);
		} or do {
			warn "json invalid: $json\n";
			return;
		};
		$urlindex++;

		if (($urlindex > 100) || ($last)) {
			my %retmap = ();
			$retmap{'bug'} = \%cvemap;
			$retmap{'embargo'} = \%embargo;
			return \%retmap;
		}

		%map = %{$mapref};

		############ Here the processing begin ###############

		my @results = @{$map{'results'}};
		foreach my $result (@results) {
			next if ($result->{'state'} eq "Merged");
			next if (($result->{'name'} =~ /CVE-/) && ($result->{'state'} eq "Not for us"));

			# creation_date
			# modified_date

			# "creation_date": "2020-12-16T18:43:44.961537+01:00",
			# print STDERR "creation: " . $result->{'creation_date'} . "\n";

			$result->{'creation_date'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d).*/;
			my $dt = DateTime->new (year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6);
			my $diff = time() - $dt->epoch;

			# only go back 1 day , as we run it more often.
			if ($diff > $refreshtime) { $last = 1; }

			#print STDERR "==== name  = " . $result->{'name'}  . "\n" if -t STDERR;
			# Only interesting if we have a bnc# entry.
			next unless ($result->{'name'} =~ /^bnc#(\d*)/);

			my $bug = $1;

			#print STDERR "==== state = " . $result->{'state'}  . "\n" if -t STDERR;
			#print STDERR Dumper($result) if -t STDERR;

			my @references = @{$result->{'references'}};
			foreach my $reference (@references) {
				if ($reference->{url} =~ /vulnId=(CVE-\d*-\d*)/) {
					my $cve = $1;
					read_smash_issue($cve,0);
					$cvemap{$cve}->{$bug} = 1;
				}
			}
			# just pull in things to the cache for now
			if ($result->{'summary'} =~ /(CVE-\d\d\d\d-\d\d\d\d\d*)/) {
				my $cve = $1;
				print STDERR "found $cve\n" if -t STDERR;
				read_smash_issue($cve,0);
				$cvemap{$cve}->{$bug} = 1;

				if ($result->{'summary'} =~ /EMBARGO/) {
					$embargo{$cve} = 1;
				}
			}
			# Find multiple CVEs...
			my $desc = $result->{'description'};
			while ($desc =~ /(CVE-\d\d\d\d-\d\d\d\d\d*)/) {
				my $cve = $1;
				print STDERR "found $cve\n" if -t STDERR;
				read_smash_issue($cve,0);
				$cvemap{$cve}->{$bug} = 1;

				$desc =~ s/$cve//g;
			}
		}
		# this will either be a query or urlindex+=1 fetch from the cache
		$url = $map{'next'};
	} while (defined($map{'next'}));

	my %retmap = ();
	$retmap{'bug'} = \%cvemap;
	$retmap{'embargo'} = \%embargo;
	return \%retmap;
}

sub
fetch_modified_smash_issues() {
	my $url = "$smashhostbase/api/issues/?category=security&ordering=-modified_date";
	my %map;
	my $urlindex = 0;
	my %cvemap = ();
	my %embargo = ();
	my $last = 0;

	my %handled = ();	# if we encounter multiple issues.

	############ JSON loader code, with caching ###############

	do {
		my $json = "";
		my $mapref;

		print STDERR "getting $url\n" if -t STDERR;

		$json = get_url($url);

		eval {
			$mapref = decode_json($json);
		} or do {
			warn "json invalid: $json\n";
			return;
		};
		$urlindex++;

		%map = %{$mapref};

		if (($urlindex > 100) || $last) {
			my %retmap = ();
			$retmap{'bug'} = \%cvemap;
			$retmap{'embargo'} = \%embargo;
			return \%retmap;
		}

		############ Here the processing begin ###############

		my @results = @{$map{'results'}};
		foreach my $result (@results) {
			next if ($result->{'state'} eq "Merged");
			next if (($result->{'name'} =~ /CVE-/) && ($result->{'state'} eq "Not for us"));

			# creation_date
			# modified_date

			# "creation_date": "2020-12-16T18:43:44.961537+01:00",
			# print STDERR "modification: " . $result->{'modified_date'} . "\n";

			$result->{'modified_date'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d).*/;
			my $dt = DateTime->new (year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6);
			my $diff = time() - $dt->epoch;

			# print STDERR "diff is $diff\n";

			# only go back 12 hours
			if ($diff > $refreshtime) { $last = 1; }

			#print STDERR "==== name  = " . $result->{'name'}  . "\n" if -t STDERR;
			# Only interesting if we have a bnc# entry.
			next unless ($result->{'name'} =~ /^bnc#(\d*)/);

			my $bug = $1;

			#print STDERR "==== state = " . $result->{'state'}  . "\n" if -t STDERR;
			#print STDERR Dumper($result) if -t STDERR;

			my @references = @{$result->{'references'}};
			foreach my $reference (@references) {
				if ($reference->{url} =~ /vulnId=(CVE-\d*-\d*)/) {
					my $cve = $1;
					read_smash_issue($cve,0);
					$cvemap{$cve}->{$bug} = 1;
				}
			}

			# just pull in things to the cache for now
			if ($result->{'summary'} =~ /(CVE-\d\d\d\d-\d\d\d\d\d*)/) {
				my $cve = $1;

				if (!defined($handled{$cve})) {
					print STDERR "refetching $cve\n" if -t STDERR;
					read_smash_issue($cve,1);
					$cvemap{$cve}->{$bug} = 1;
					$handled{$cve} = 1;
				}
				if ($result->{'summary'} =~ /EMBARGO/) {
					$embargo{$cve} = 1;
				}
			}
			# Find multiple CVEs...
			my $desc = $result->{'description'};
			while ($desc =~ /(CVE-\d\d\d\d-\d\d\d\d\d*)/) {
				my $cve = $1;
				if (!defined($handled{$cve})) {
					print STDERR "refetching $cve\n" if -t STDERR;
					read_smash_issue($cve,1);
					$cvemap{$cve}->{$bug} = 1;
					$handled{$cve} = 1;
				}

				$desc =~ s/$cve//g;
			}
		}
		# this will either be a query or urlindex+=1 fetch from the cache
		$url = $map{'next'};
	} while (defined($map{'next'}));

	my %retmap = ();
	$retmap{'bug'} = \%cvemap;
	$retmap{'embargo'} = \%embargo;
	return \%retmap;
}


sub
invalidate_smash_issue($) {
	my ($cve) = @_;
	read_smash_issue($cve,1);
}

sub
get_cvss_issue($) {
	my ($issuenr) = @_;

	read_smash_issue($issuenr,0);

	return \%{$SMASHData::cvss{$issuenr}};
}

sub
get_cvssv3_issue($) {
	my ($issuenr) = @_;

	read_smash_issue($issuenr,0);

	return \%{$SMASHData::cvssv3{$issuenr}};
}

sub
get_cvssv4_issue($) {
	my ($issuenr) = @_;

	read_smash_issue($issuenr,0);

	return \%{$SMASHData::cvssv4{$issuenr}};
}

## read all (cached) smash issues.
sub
read_all_cached_issues() {
	print STDERR "Reading all smash issues...\n" if -t STDERR;
	my @allcves = <$cverepobase/smash/issue2/CVE*.0>;
	foreach my $cve (@allcves) {
		$cve =~ s/.0$//;
		$cve =~ s/^.*\///;
		read_smash_issue($cve,0);
	}
	print STDERR "Reading all smash issues... done\n" if -t STDERR;
}

#read_smash_issue("CVE-2022-0001",0);
#read_smash_issue("CVE-2023-38289",0);
read_smash_issue("CVE-2024-6387",0);

#print Dumper(\%SMASHData::codestreampkgstate);
#print Dumper(\%SMASHData::pkgstate);
#print Dumper(\%SMASHData::cvssv3);
#print Dumper(\%SMASHData::vendoradvisories);
#read_all_cached_issues();
#print Dumper(\%SMASHData::prod2cpe);

#fetch_last_smash_issues();


read_embargoed_bugs();

1;
