1
0
mirror of https://git.FreeBSD.org/ports.git synced 2025-01-27 10:03:20 +00:00
freebsd-ports/security/ca_root_nss/files/MAca-bundle.pl.in
Matthias Andree 35f2e5abb5 Support WITH_DEBUG=yes to get more debug output from the bundle
creation, to verbosely print omitted and included certificates.

Approved by:	flo@ on "as long as you fix it if it breaks" condition
2013-02-20 08:07:13 +00:00

202 lines
5.1 KiB
Perl

##
## MAca-bundle.pl -- Regenerate ca-root-nss.crt from the Mozilla certdata.txt
##
## Rewritten in September 2011 by Matthias Andree to heed untrust
##
## Copyright (c) 2011, 2013 Matthias Andree <mandree@FreeBSD.org>
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
##
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
##
## * 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.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "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
## COPYRIGHT HOLDER OR CONTRIBUTORS 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.
use strict;
use MIME::Base64;
my $VERSION = '$FreeBSD$';
# configuration
print <<EOH;
##
## ca-root-nss.crt -- Bundle of CA Root Certificates
##
## This is a bundle of X.509 certificates of public Certificate
## Authorities (CA). These were automatically extracted from Mozilla's
## root CA list (the file `certdata.txt').
##
## Extracted from nss-%%VERSION_NSS%%
## with $VERSION
##
EOH
my $debug = 0;
$debug++
if defined $ENV{'WITH_DEBUG'}
and $ENV{'WITH_DEBUG'} !~ m/(?i)^(no|0|false|)$/;
my %certs;
my %trusts;
sub printcert_plain($$)
{
my ($label, $certdata) = @_;
print "=== $label ===\n" if $label;
print
"-----BEGIN CERTIFICATE-----\n",
MIME::Base64::encode_base64($certdata),
"-----END CERTIFICATE-----\n\n";
}
sub printcert_info($$)
{
my (undef, $certdata) = @_;
return unless $certdata;
open(OUT, "|openssl x509 -text -inform DER -fingerprint")
|| die "could not pipe to openssl x509";
print OUT $certdata;
close(OUT) or die "openssl x509 failed with exit code $?";
}
sub printcert($$) {
my ($a, $b) = @_;
printcert_info($a, $b);
}
sub graboct()
{
my $data;
while (<>) {
last if /^END/;
my (undef,@oct) = split /\\/;
my @bin = map(chr(oct), @oct);
$data .= join('', @bin);
}
return $data;
}
sub grabcert()
{
my $certdata;
my $cka_label;
my $serial;
while (<>) {
chomp;
last if ($_ eq '');
if (/^CKA_LABEL UTF8 "([^"]+)"/) {
$cka_label = $1;
}
if (/^CKA_VALUE MULTILINE_OCTAL/) {
$certdata = graboct();
}
if (/^CKA_SERIAL_NUMBER MULTILINE_OCTAL/) {
$serial = graboct();
}
}
return ($serial, $cka_label, $certdata);
}
sub grabtrust() {
my $cka_label;
my $serial;
my $trust = 1;
while (<>) {
chomp;
last if ($_ eq '');
if (/^CKA_LABEL UTF8 "([^"]+)"/) {
$cka_label = $1;
}
if (/^CKA_SERIAL_NUMBER MULTILINE_OCTAL/) {
$serial = graboct();
}
if (/^CKA_TRUST_.*\s.*_(UN|NOT_)TRUSTED/) {
$trust = 0;
}
}
return ($serial, $cka_label, $trust);
}
while (<>) {
if (/^CKA_CLASS .* CKO_CERTIFICATE/) {
my ($serial, $label, $certdata) = grabcert();
if (defined $certs{$label."\0".$serial}) {
warn "Certificate $label duplicated!\n";
}
$certs{$label."\0".$serial} = $certdata;
} elsif (/^CKA_CLASS .* CKO_(NSS|NETSCAPE)_TRUST/) {
my ($serial, $label, $trust) = grabtrust();
if (defined $trusts{$label."\0".$serial}) {
warn "Trust for $label duplicated!\n";
}
$trusts{$label."\0".$serial} = $trust;
} elsif (/^CVS_ID.*Revision: ([^ ]*).*/) {
print "## Source: \"certdata.txt\" CVS revision $1\n##\n\n";
}
}
sub printlabel(@) {
my @res = @_;
map { s/\0.*//; s/[^[:print:]]/_/g; $_ = "\"$_\""; } @res;
return wantarray ? @res : $res[0];
}
# weed out untrusted certificates
my $untrusted = 0;
foreach my $it (keys %trusts) {
if (!$trusts{$it}) {
if (!exists($certs{$it})) {
warn "Found trust for nonexistent certificate ".printlabel($it)."\n" if $debug;
} else {
delete $certs{$it};
warn "Skipping untrusted ".printlabel($it)."\n" if $debug;
$untrusted++;
}
}
}
print "## Untrusted certificates omitted from this bundle: $untrusted\n\n";
my $certcount = 0;
foreach my $it (sort {uc($a) cmp uc($b)} keys %certs) {
if (!exists($trusts{$it})) {
die "Found certificate without trust block,\naborting";
}
printcert("", $certs{$it});
print "\n\n\n";
$certcount++;
print STDERR "Trusting $certcount: ".printlabel($it)."\n" if $debug;
}
print "## Number of certificates: $certcount\n";
print "## End of file.\n";