[Fedora-security-commits] fedora-security/tools/lib/Libexig Audit.pm, 1.1, 1.2 Bodhi.pm, 1.1, 1.2 CVE.pm, 1.1, 1.2 Fedora.pm, 1.1, 1.2 Util.pm, 1.1, 1.2

fedora-security-commits at redhat.com fedora-security-commits at redhat.com
Mon Jan 14 16:04:49 UTC 2008


Author: lkundrak

Update of /cvs/fedora/fedora-security/tools/lib/Libexig
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv17363/lib/Libexig

Added Files:
	Audit.pm Bodhi.pm CVE.pm Fedora.pm Util.pm 
Log Message:
Merging (hopefully) stable from my branch



Index: Audit.pm
===================================================================
RCS file: Audit.pm
diff -N Audit.pm
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Audit.pm	14 Jan 2008 16:04:47 -0000	1.2
@@ -0,0 +1,130 @@
+# $Id$
+# Audit database interface
+# Lubomir Kundrak <lkundrak at redhat.com>
+
+package Libexig::Audit;
+
+use Libexig::Util;
+
+use warnings;
+use strict;
+
+# Get lines from file and parse them
+sub new
+{
+	my $class = shift;
+	my $self = shift;
+
+	# Read standard input unless specified otherwise
+	$self->{file} = '-' unless $self->{file};
+
+	open (AUDIT, $self->{file})
+		or die "Could not open $self->{file}";
+
+	$self->{audit} = [];
+	push @{$self->{audit}}, parse_line ($_) foreach <AUDIT>;
+
+	close (AUDIT);
+
+	bless $self, $class;
+	return $self;
+}
+
+# Add an entry, to the proper place alphabetically
+sub add
+{
+	my $self = shift;
+	my $entry = shift;
+	my $index;
+
+	for ($index = 0; $index <= $#{$self->{audit}}; $index++) {
+		$self->{audit}->[$index]->{cve} or next;
+		$self->{audit}->[$index]->{cve} lt $entry->{cve} and last;
+	};
+
+	update_entry ($entry);
+	use Data::Dumper;
+	parse_line ($entry->{line}); # Check if it is well formed
+	insert ($self->{audit}, $index, $entry);
+}
+
+# Save
+sub save
+{
+	my $self = shift;
+
+	open (AUDIT, '>'.$self->{file})
+		or die "Could not open $self->{file}";
+
+	foreach my $entry (@{$self->{audit}}) {
+		#update_entry ($entry);
+		print AUDIT $entry->{line};
+	}
+
+	close (AUDIT);
+}
+
+# Get an entry hash and reconstruct its 'line' field
+# (useful if something got changed)
+sub update_entry
+{
+	my $entry = shift;
+
+	$entry->{cve} or return;
+	$entry->{line} = join " ", (
+		$entry->{need_verif}.$entry->{cve},
+		$entry->{status},
+		($entry->{fixed}
+			? "($entry->{component}, $entry->{fixed})"
+			: "($entry->{component})"),
+		($entry->{bug}
+			? "#$entry->{bug}"
+			: ()),
+		($entry->{since}
+			? "[since $entry->{since}]"
+			: ()),
+		$entry->{comment}
+	);
+
+	chomp $entry->{line};
+	$entry->{line} .= "\n";
+}
+
+# Get line and return a hash
+sub parse_line
+{
+	$_ = shift;
+	if (/^#/ or /^\s*$/) {
+		return {
+			'line'		=> $_,
+		};
+	} elsif (/^
+		(\*?)*							# Needs verification
+		(\S+-\S+-\S+)\s*					# CVE
+		(\*\*|version|VULNERABLE|ignore|backport|fixed)\s*	# Status
+		\(
+			([^\s,]+)\s*					# Component
+			(,\s*(.*))?\s*					# When fixed upstream
+		\)\s*			
+		(\#(\d+))?\s*						# Bugzilla IS
+		(\[since\s+(\S+)\])?\s*					# When fixed in Fedora
+		(.*)							# Comment
+	/x) {
+		return {
+			need_verif	=> $1,
+			cve		=> $2,
+			status		=> $3,
+			component	=> $4,
+			fixed		=> $6,
+			bug		=> $8,
+			since		=> $10,
+			comment		=> $11,
+			line		=> $_,
+		};
+		next;
+	} else {
+		die "Prase error: $_";
+	}
+}
+
+0.99999;


Index: Bodhi.pm
===================================================================
RCS file: Bodhi.pm
diff -N Bodhi.pm
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Bodhi.pm	14 Jan 2008 16:04:47 -0000	1.2
@@ -0,0 +1,107 @@
+# $Id$
+# This is how do we interface with the Fedora Update System
+# Lubomir Kundrak <lkundrak at redhat.com>
+
+package Libexig::Bodhi;
+
+use JSON;
+
+# Convert the text blob from bodhi to a hash,
+# dissect some multipart values
+sub update_to_hashref
+{
+	my @lines = split /\n/, shift;
+	my %retval;
+	my $line;
+	my $name;
+
+	# Rougly process all the fields and header
+	
+	while ($line = shift @lines) {
+
+		# Header
+		if ($line eq "=" x 80) {
+			$retval{'_NVR'} = '';
+
+			do {
+				$line = shift @lines;
+				$line =~ /\s+(.*)/ and $retval{'_NVR'} .= $1;
+			} while ($line ne '=' x 80);
+
+		# Additional comment lines do not have leading :
+		# This causes havoc on comments including : character
+		} elsif ($line =~ /^\s*(Comments): (.*)/) {
+			$name = $1;  # always 'Comments'
+			$retval{$name} = $2;
+
+			# expect comments until blank line
+			$line = shift @lines;
+			while (defined($line)  &&  $line !~ /^$/) {
+				$line =~ s/^\s*//;
+				$retval{$name} .= "\n$line";
+				$line = shift @lines;
+			}
+
+		# Blah: blah
+		} elsif ($line =~ /\s*([^:]*): (.*)/) {
+			$name = $1 if ($1);
+			if (defined $retval{$name}) {
+				$retval{$name} .= "\n$2";
+			} else {
+				$retval{$name} = $2;
+			}
+
+		# Update URL
+		} elsif ($line =~ /^  (http.*)/) {
+			$retval{'_Update URL'} = "$1";
+		}
+	}
+
+	# Grok bug strings
+
+	if ($retval{'Bugs'}) {
+		my %bugs;
+		my $bug;
+
+		foreach (split /\n/, $retval{'Bugs'}) {
+			if (/(\d+) - (.*)/) {
+				$bug = $1;
+				$bugs{$bug} = $2;
+			} else {
+				#$bugs{$bug} .= " $2";
+			}
+		}
+
+		$retval{'_Bugs'} = \%bugs;
+	}
+	
+	# Grok raw NVR list
+
+	my @nvrs = split /,\s*/, $retval{'_NVR'};
+	$retval{'_NVRs'} = \@nvrs;
+
+	# Parsing comments, not yet implemented, of no use for us
+
+	return \%retval;
+}
+
+# Get array of all updates for a package
+sub get_updates
+{
+	my $pkg = shift or die 'No package name supplied';
+	my @retval;
+
+	
+	# Get updates
+	$json = `wget --post-data 'package=$pkg&tg_paginate_limit=0' -qO - \\
+			'https://admin.fedoraproject.org/updates/list?tg_format=json'`;
+	$obj = jsonToObj ($json);
+
+	foreach my $update (@{$obj->{'updates'}}) {
+		push @retval, update_to_hashref ($update);
+	}
+
+	return @retval;
+}
+
+1;


Index: CVE.pm
===================================================================
RCS file: CVE.pm
diff -N CVE.pm
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CVE.pm	14 Jan 2008 16:04:47 -0000	1.2
@@ -0,0 +1,123 @@
+# $Id$
+# Get CVE information from NVD and maintain NVD XML file cache
+# Lubomir Kundrak <lkundrak at redhat.com>
+
+package Libexig::CVE;
+
+#use warnings;
+#use strict;
+
+use Exporter 'import';
+use XML::Parser;
+use LWP::Simple;
+
+ at EXPORT = qw/cve/;
+
+my $sourcebase = 'http://nvd.nist.gov/download/';
+my $cachebase = $ENV{'HOME'}.'/.nvdcache/';
+
+my $parser = new XML::Parser (
+	'Style'	=> 'Tree',
+);
+
+sub get_element
+{
+	my $tree = shift;
+
+	my $tag = shift @{$tree};
+	my $content = shift @{$tree};
+	my $arguments = shift @{$content};
+
+	if ($tag and $content and $arguments) {
+		return [$tag, $content, $arguments];
+	} else {
+		return undef;
+	}
+}
+
+# Gets <desc> element and returns description from 'cve' source
+sub get_desc
+{
+	my $e = shift;
+
+	while (my $e = get_element ($e->[1])) {
+		# <descript>
+		$e->[2]->{'source'} eq 'cve' or next;
+		return $e->[1]->[1];
+	}
+}
+
+# Gets <refs> element and returns array of all url=s of <ref>s
+sub get_refs
+{
+	my $e = shift;
+	my @refs;
+
+	while (my $e = get_element ($e->[1])) {
+		# <ref>
+		push @refs, $e->[2]->{'url'};
+	}
+
+	return @refs;
+}
+
+# Get <entry> and return its description and references
+sub do_entry
+{
+	my $e = shift;
+	my $desc;
+	my @refs;
+
+	$e->[2]->{'type'} eq 'CVE' or die 'Non-CVE entry';
+
+	while (my $e = get_element ($e->[1])) {
+		$desc = get_desc ($e) if $e->[0] eq 'desc';
+		@refs = get_refs ($e) if $e->[0] eq 'refs';
+
+		$desc and @refs and return ($desc, [@refs]);
+	}
+}
+
+# Update file in cache if older than age and return its path
+sub nvdcache
+{
+	my ($file, $age) = @_;
+
+	mkdir $cachebase;
+	system ("mkdir -p '$cachebase'");
+	mirror ($sourcebase.$file, $cachebase.$file)
+		or die ('Failed to update cache');
+	return $cachebase.$file;
+}
+
+# lala
+sub cve 
+{
+	my $cve = shift;
+	
+	$cve =~ /^CVE-(\d+)-\d+$/ or die "'$cve' does not look like a CVE id";
+	my $year = ($1 > 2002 ? $1 : 2002);
+
+	foreach (
+		# File name => cache update threshold (minutes, XXX: not implemented)
+		# order is important
+		[ 'nvdcve-modified.xml'	=> 0	],
+		[ 'nvdcve-recent.xml'	=> 0	],
+		[ 'nvdcve-'.$year.'.xml' => 1440 ],
+	) {
+		my $file = nvdcache (@{$_});
+		my $tree = $parser->parsefile ($file);
+		my $e = get_element ($tree);
+
+		while (my $e = get_element ($e->[1])) {
+			# matching <entry name="$cve">
+			if ($e->[0] eq 'entry' and $e->[2]->{'name'} eq $cve) {
+				return do_entry ($e);
+			}
+		}
+	}
+
+	return undef;
+}
+
+1;


Index: Fedora.pm
===================================================================
RCS file: Fedora.pm
diff -N Fedora.pm
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Fedora.pm	14 Jan 2008 16:04:47 -0000	1.2
@@ -0,0 +1,255 @@
+# $Id$
+# Fedora specific routines and constants
+# Lubomir Kundrak <lkundrak at redhat.com>
+
+package Libexig::Fedora;
+
+use warnings;
+use strict;
+
+%Libexig::Fedora::srt_bz_map = (
+	'critical'	=> 'urgent',
+	'important'	=> 'high',
+	'moderate'	=> 'medium',
+	'low'		=> 'low',
+);
+
+###
+### Parent bugs from CVE
+###
+
+# Get the text to include in the CVE bug descripiton
+sub cve_bug_desc
+{
+	my $cve = shift;
+	my $desc = shift;
+	my $refs = shift;
+
+	return
+		"Common Vulnerabilities and Exposures assigned an ".
+		"identifier $cve to the following vulnerability:".
+		"\n\n".
+		($desc ? $desc : '(Please paste the CVE details manually)').
+		"\n\n".
+		"References:\n\n".
+		($refs ? join ("\n", @{$refs}) : '(References here, one per line)');
+}
+
+# Construct the parent bug
+sub cve_bug
+{
+	my $cve = shift;
+	my $component = shift;
+	my $summary = shift;
+	my $desc = shift;
+	my $impact = shift;
+	my $bugzilla = shift;
+
+	# Get CC list
+	# TODO: get rid of duplicates
+	my @cc;
+	foreach (split (/,/,$component)) {
+		push (@cc,$bugzilla->owners ($_));
+	}
+
+	return (
+		'bug_file_loc'	=> "http://nvd.nist.gov/nvd.cfm?cvename=$cve",
+		'rep_platform'	=> 'All',
+		'op_sys'	=> 'Linux',
+		'short_desc'	=> "$cve $summary",
+		'keywords'	=> 'Security',
+		'product'	=> 'Security Response',
+		'comment'	=> $desc,
+		'component'	=> 'vulnerability',
+		'bug_severity'	=> $Libexig::Fedora::srt_bz_map{$impact},
+		'priority'	=> $Libexig::Fedora::srt_bz_map{$impact},
+		'version'	=> 'unspecified',
+		'cc'		=> join (',', @cc),
+		'alias'		=> $cve,
+	);
+}
+
+###
+### Tracking bugs
+###
+
+my $comment_head = 
+	'This is an automatically created tracking bug! '.
+	'It was created to ensure that one or more security '.
+	'vulnerabilities are fixed in all affected branches.'.
+	"\n\n".
+	'You should *not* refer to this bug publicly, as it is a '.
+	'private "Fedora Project Contributors" bug.'.
+	"\n\n".
+	'For comments that are specific to the vulnerability please use bugs '.
+	'filed against "Security Response" product referenced in "Blocks" '.
+	'field.'.
+	"\n\n";
+
+my $comment_tail = 
+	'For more information see: '.
+	'http://fedoraproject.org/wiki/Security/TrackingBugs';
+
+my $comment_update = 
+	# Following the list of parent bugs
+	"\n".
+	'When creating an update for the version this this bug is reported '.
+	'against please include the bug IDs of respective bugs filed '.
+	'against "Security Response" product as well as of this bug and let the '.
+	'update system close them. Please '.
+	'note that the update announcement will (and should) contain only '.
+	'references to "Security Response" bugs as long as the tracking '.
+	'bug is restricted to "Fedora Project Contributors".'.
+	"\n\n";
+
+my $comment_rawhide = 
+	"\n".
+	'Please close this bug with RAWHIDE (referencing appropriate N-V-R in '.
+	'Fixed In field if possible) once is it fixed in devel branch. '.
+	'Do *not* include the bug id of this bug in the RPM changelog and the '.
+	'commit message.'.
+	"\n\n";
+
+my %priorities = (
+	'urgent',	=> 4,
+	'high',		=> 3,
+        'medium',	=> 2,
+	'low'		=> 1,
+);
+
+# Valid versions
+my %versions = (
+	'6',		=> '6',
+	'f6',		=> '6',
+	'fc6',		=> '6',
+	'7',		=> '7',
+	'f7',		=> '7',
+	'fc7',		=> '7',
+	'8',		=> '8',
+	'f8',		=> '8',
+	'fc8',		=> '8',
+	'9',		=> 'rawhide',
+	'f9',		=> 'rawhide',
+	'fc9',		=> 'rawhide',
+	'devel',	=> 'rawhide',
+);
+
+sub tracking_bugs
+{
+	my $bugs = shift;
+	my $component = shift;
+	my @versions = @_;
+
+	my @retval;
+
+	# Construct a tracking bug template
+
+	my %bug_tmpl = (
+		'bug_file_loc'	=> 'http://fedoraproject.org/wiki/Security/TrackingBugs',
+		'rep_platform'	=> 'All',
+		'op_sys'	=> 'Linux',
+		'short_desc'	=> '',
+		'keywords'	=> 'Security',
+		'product'	=> 'Fedora',
+		'component'	=> $component,
+		'bug_severity'	=> 'low',
+		'priority'	=> 'low',
+		'bit-58'	=> '1', # Fedora Project Contributors
+	);
+
+	my $comment_parents = '';
+
+	foreach my $bug (@{$bugs}) {
+
+		# Take the highest of priorities
+		$bug_tmpl{'bug_severity'} = $bug->{'bug_severity'}
+			if ($priorities{$bug->{'bug_severity'}} > $priorities{$bug_tmpl{'bug_severity'}});
+		$bug_tmpl{'priority'} = $bug->{'priority'}
+			if ($priorities{$bug->{'priority'}} > $priorities{$bug_tmpl{'priority'}});
+
+		# This will be overwriten if we block just one parent bug
+		$bug_tmpl{'short_desc'} .= $bug->{'alias'}.' ';
+
+		# Add the parent bug to the comment
+		$comment_parents .= "\tbug #$bug->{'bug_id'}: $bug->{'short_short_desc'}\n";
+	}
+
+	if (@{$bugs} > 1) {
+		$bug_tmpl{'short_desc'} .= "Multiple $component vulnerabilities";
+	} else {
+		$bug_tmpl{'short_desc'} = $bugs->[0]->{'short_short_desc'};
+	}
+
+	# Create a bug hash for each version
+
+	foreach my $version (@versions) {
+		my %bug = %bug_tmpl;
+		$bug{'short_desc'} .= " [Fedora $versions{$version}]";
+		$bug{'version'} = $versions{$version};
+
+		$bug{'comment'} =
+			$comment_head.
+			$comment_parents.
+			($bug{'version'} eq 'rawhide' ? $comment_rawhide : $comment_update).
+			$comment_tail;
+
+		push @retval, \%bug;
+	}
+
+	return \@retval;
+}
+
+# file_tracking_bugs
+#
+# Arguments:
+# - ref to list of parent bug ids
+# - ref to list of bugs to file (each element must be hash as expected by BZ)
+#   this list is prepared by tracking_bugs
+# - Bugzilla object reference
+# - component
+sub file_tracking_bugs
+{
+	my $parent_bugs = shift;
+	my $tracking_bugs = shift;
+	my $bugzilla = shift;
+	my $component = shift;
+
+	my $comment = "Created Fedora tracking bugs for $component:\n\n";
+
+	foreach my $bug (@{$tracking_bugs}) {
+		use Data::Dumper;
+		my $bug_id = $bugzilla->file_bug ($bug);
+
+		if (!defined($bug_id)) {
+			print STDERR "Error: Bug creation failed! (dryrun mode?)\n";
+			#return undef;
+		}
+
+		### XXX: Move this somewhere else?
+		if ($bug->{'version'} ne 'rawhide') {
+			my $tr_comment = 
+				'You can eventually use the following link to '.
+				'create the update request: '."\n".
+				'https://admin.fedoraproject.org/updates/new/'.
+				'?request=Stable'.
+				'&type=security'.
+				'&release=Fedora%20'.$bug->{'version'}.
+				'&bugs='.$bug_id;
+
+			foreach my $bug (@{$parent_bugs}) {
+				$tr_comment .= ','.$bug;
+			}
+
+			$bugzilla->add_comment ($bug_id, $tr_comment);
+		}
+
+		$bugzilla->add_blockers ($bug_id, $parent_bugs);
+		$comment .= $bug->{'version'}.": bug #$bug_id\n";
+	}
+
+	foreach my $bug (@{$parent_bugs}) {
+		$bugzilla->add_private_comment ($bug, $comment);
+	}
+
+	return $comment;
+}


Index: Util.pm
===================================================================
RCS file: Util.pm
diff -N Util.pm
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Util.pm	14 Jan 2008 16:04:47 -0000	1.2
@@ -0,0 +1,54 @@
+# $Id$
+# Random routines that are shared across the tooling
+# Lubomir Kundrak <lkundrak at redhat.com>
+
+package Libexig::Util;
+
+#use warnings;
+#use strict;
+
+use Exporter 'import';
+use File::Temp ('tempfile');
+
+ at EXPORT = qw/edit_string read_noecho insert/;
+
+# Launch an editor for editing the bugzilla comment or whatever
+sub edit_string
+{
+	my $string = shift;
+
+	my ($tmpfh, $tmpname) = tempfile ();
+	print $tmpfh $string;
+	close ($tmpfh);
+	my $editor = ($ENV{'EDITOR'} or 'vi');
+	system ($editor, $tmpname);
+	open ($tmpfh, "<$tmpname");
+	$string = join ('', <$tmpfh>);
+	close ($tmpfh);
+
+	return $string;
+}
+
+# Get password not echoing characters
+sub read_noecho
+{
+	print STDERR @_;
+	system ('stty -echo');
+	my $string = <STDIN>;
+	system ('stty echo');
+	chomp ($string);
+	print STDERR "\n";
+	$string;
+}
+
+# Insert a sub-list into a list
+sub insert
+{
+	my $array = shift;
+	my $index = shift;
+	my @what = @_;
+
+	splice (@{$array}, $index, 0, @what);
+}
+
+1;




More information about the Fedora-security-commits mailing list