#!/usr/bin/perl
use strict;

# File under Perl Artistic Licence 2.0
# http://www.opensource.org/licenses/artistic-license-2.0.php

# Copyright holder: TBS INTERNET SAS, France
# Author: JP Donnio
# Contact: tag-nss-restrict_ca@tbs-internet.com
# http://www.tbs-certificats.com/
#
# Doc at: http://www.tbs-certificats.com/ssl/nss_tools_crl_ca_control.html
#
# Version: 1.0
# Date: 2008-08-20

# USAGE: nss_restrict_ca [--builtin] <cert8.db directory location>

my $DEBUG=0;
my $VERBOSE=1;

# process the default or the builtin store?
# use --builtin for the builtin store
my $BUILTINONLY;
my $hwdev;
if ($ARGV[0] =~ /-{1,2}builtin/) {
	$BUILTINONLY="Builtin Object Token:";
	$hwdev="-h \"Builtin Object Token\"";
	shift @ARGV;
}

# set default DB dir
my $DBDIR;
if ( -d "$ARGV[0]" ) {
	$DBDIR=$ARGV[0];
} else {
	# SET HERE your firefox/mozilla/you-name-it directory
	# must contain cert8.db
	$DBDIR="$ENV{HOME}/.mozilla/default/m8xsi8n3.slt/";
}




my $CERTLIST="$ENV{HOME}//bin/nss_restrict_ca.list";

my $CERTUTIL="/usr/bin/certutil";

my %trusted;

# lets load the trusted list
open FHCERTLIST, $CERTLIST or die "Could not open $CERTLIST";
while (<FHCERTLIST>) {
	chomp;
	next if /^\s*#/;
	next if /^\s*$/;
	my ($thecn,$theflag) = split /\t/;
	$thecn =~ s/\s+$//;
	$trusted{"$thecn"}=$theflag;
}
close FHCERTLIST;


# read the database
if (open NSSLIST, "$CERTUTIL -L $hwdev -d \"$DBDIR\" |") { 
	while (<NSSLIST>) { 
		chomp;
		next if (/\s+[uUpP]*,[uUpP]*,[uUpP]*\s*$/); # dont care about peer or user certs
		if (/$BUILTINONLY(.*)\s+([cTCG]*,[cTC]*,[cTC]*)\s*$/) { # found, save the CN and the flags
			my $nsscn=$1;
			my $nssflag=$2;
			$nsscn =~ s/\s+$//;

			if (! $trusted{"$nsscn"}) { # we do not trust this item, make sure it is inactive
				my $newflag=lc($nssflag);
				$newflag =~ s/t//g;	# lower case t does not exist

# 				# we need to ignore the G (stepup)
 				my $cmp1 = $newflag; $cmp1 =~ s/g//ig;
 				my $cmp2 = $nssflag; $cmp2 =~ s/g//ig;

 				if ($cmp1 ne $cmp2) {
					my $rc = 0xffff & system("$CERTUTIL -M $hwdev -d \"$DBDIR\" -n \"$BUILTINONLY$nsscn\" -t \"$newflag\" ");
					if ($rc != 0) {
						print "Failed to change flags of $nsscn to $newflag with error $rc\n\n";
					} else {
						print "Info: disabled $nsscn (was $nssflag now $newflag)\n" if ($VERBOSE);
					}
 				}
			} else {
				# WE TRUST IT - make sure the flags are the same
				if ($trusted{"$nsscn"} ne $nssflag) { # hmm, lets correct the flags

					# we need to ignore the G
					my $cmp1 = $trusted{"$nsscn"}; $cmp1 =~ s/g//ig;
					my $cmp2 = $nssflag; $cmp2 =~ s/g//ig;

					if ($cmp1 ne $cmp2) {
						my $rc = 0xffff & system("$CERTUTIL -M $hwdev -d \"$DBDIR\" -n \"$BUILTINONLY$nsscn\" -t \"$trusted{$nsscn}\" ");
						if ($rc != 0) {
							print "Failed to change flags of trusted $nsscn to $trusted{$nsscn} (was $nssflag) with error $rc\n\n";
						} else {
							print "Warning: flags of trusted $nsscn was reset to $trusted{$nsscn} (was $nssflag)\n";
						}
					}
				}
			}
		} else {
			print "MISMATCH:$_\n" if ($DEBUG);
		}
	}
} else {
	die "Failed to call $CERTUTIL\n";
}
close NSSLIST;


