#!/usr/bin/perl use strict; use File::Basename; use File::Glob; # File under Perl Artistic Licence 2.0 # http://www.opensource.org/licenses/artistic-license-2.0.php # Copyright holder: TBS INTERNET SAS, France # Author: PALLAVIDINO Luc # 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.2 # Date: 2009-05-13 #------------------------------------------------------------------------- # Version: 1.1 # Date: 2009-05-05 #------------------------------------------------------------------------- # Version: 1.0 # Date: 2009-03-06 # USAGE: nss_root_util [--builtin] [-norestrictca] [-noupdatecrl] [nocache] [-h] my $caPolicyName = 'nss_restrict_ca.list'; my $crlPolicyName = 'nss_update_crl.list'; my $defaultPolicyDir = '/etc/'; # nssRestrictCa application location my $nssRestrictCa = '/usr/local/bin/nss_restrict_ca'; # nssUpdateCrl application location my $nssUpdateCrl = '/usr/local/bin/nss_update_crl'; # fichier d'exclusion my $exclusionFile = 'nss_root_util_exclusion.list'; # fichier de log my $logFile = '/var/log/nss_root_util.log'; # On recupere l'argument --Builtin my $builtIn = ''; if ($ARGV[0] =~ /-{1,2}builtin/) { $builtIn = '--builtin'; } # On recupere l'argument -norestrictca, -noupdatecrl et -nocache # si ils existent my $noRCA = 1; my $noUCRL = 1; my $noCache = ""; foreach my $it (@ARGV) { if($it =~ /^-{0,2}norestrictca$/) { $noRCA = 0; } if($it =~ /^-{0,2}noupdatecrl$/) { $noUCRL = 0; } if($it =~ /^-{0,2}nocache$/) { $noCache = "nocache"; } if($it =~ /^-{0,2}h$/) { print "USAGE : $0 [--builtin] [-norestrictca] [-noupdatecrl] [-nocache]\ \t--builtin : works on the builtin object token\ \t-norestrictca : don't use the nss restrict ca util\ \t-noupdatecrl : don't use the nss update crl util\ \t-nocache : don't cache CRLs downloaded\n"; exit 0; } } # On teste la validite des variables de configuration if ( ! -e $nssRestrictCa ) { print "Unable to access to 'nss_restrict_ca'\n"; exit; } if ( ! -e $nssUpdateCrl ) { print "Unable to access to 'nss_update_crl'\n"; exit; } # Liste d'arguments (liste de tableaux associatif composé d'un champ indiquant l'emplacement # du fichier nss, un second champ indiquant l'emplacement de la politique de la restriction des CA à utiliser, # et un dernier champ indiquant l'emplacement de la politique de la mise à jour des CRLs) my @lstArgs = (); # Permet de trouver les repertoire cert8.db de tous les utilisateurs et d'y associer # la politique globale ou locale # /!\ Seulement les repertoires cert8.db relatifs aux produits mozilla my $caPolicy; my $crlPolicy; my @tabExcl = (); # Fichier de log open(WRITER,">> ".$logFile) || die ("Error : unable to open log file !\n"); print WRITER "* NSS_ROOT_UTIL LOG : ".localtime(time)."\n"; #On crée le tableau contenant la liste des exclusions unless (open(FH,$defaultPolicyDir.$exclusionFile)) { print WRITER "Error : unable to open exclusion file\n"; close(WRITER); die ("Error : unable to open exclusion file"); } while () { next if /^\s*#/; next if /^\s*$/; chomp($_); push(@tabExcl, $_); } close(FH); #On recherche tous les repertoires de connexion des utilisateurs my $userFile='/etc/passwd'; unless (open(FH,$userFile)) { print WRITER "Error : unable to open /etc/passwd\n"; close(WRITER); die ("Error : unable to open /etc/passwd"); } while () { #On decoupe les entrées du fichier passwd afin de recuperer les repertoires de connexion my @tabTmp = split(/:/, $_); my $flagNext = 0; # si on trouve l'exclusion d'un utilisateur on passe à l'utilisateur suivant foreach my $it (@tabExcl) { if($it eq $tabTmp[0]) { $flagNext = 1; last; } } next if($flagNext == 1); unless (open(FHEX,$defaultPolicyDir.$exclusionFile)) { print WRITER "Error : unable to open exclusion file\n"; close(WRITER); die ("Error : unable to open exclusion file"); } foreach(glob($tabTmp[5]."/.{mozilla,thunderbird,mozilla-thunderbird,firefox}/*/*/cert8.db")) { # si on trouve l'exclusion d'un utilisateur on passe à l'utilisateur suivant my $flagNext1 = 0; foreach my $it (@tabExcl) { if($_ =~ /^$it.*/) { $flagNext1 = 1; last; } } next if($flagNext1 == 1); $caPolicy = $defaultPolicyDir.$caPolicyName; $crlPolicy = $defaultPolicyDir.$crlPolicyName; #On verifie si l'utilisateur a une politique locale (CA) if( -e dirname($_)."/".$caPolicyName) { $caPolicy = dirname($_).$caPolicyName; } #On verifie si l'utilisateur a une politique locale (CRL) if( -e dirname($_)."/".$crlPolicyName) { $crlPolicy = dirname($_).$crlPolicyName; } #On enregistre les triplets fichier cert8.db, police CA, police CRL push(@lstArgs, {"nssFile" => dirname($_),"caPolicy" => $caPolicy,"crlPolicy" => $crlPolicy}); } } close(FH); # On lance le programme de mise à jour des CRLs if($noUCRL == 1) { foreach (@lstArgs) { next if (! -d "$_->{nssFile}" or ! -e "$_->{crlPolicy}"); my $logFileTmp = $logFile.rand(); system("$nssUpdateCrl \"$_->{nssFile}\" \"$_->{crlPolicy}\" \"$noCache\" 2>&1 >> $logFileTmp"); open(READER,"< ".$logFileTmp) || die ("Error : unable to open temp log file !\n"); open(WRITER,">> ".$logFile) || die ("Error : unable to open log file !\n"); # On parcourt le fichier de log temporaire afin de vérifier si l'on doit rediriger une erreur vers la sortie std (afin d'envoyer un mail de notification via cron) while (my $log = ) { # Si une erreur commence par un # on l'écrit sur la sortie std if( $log =~ s/^\s*#//g) { print("NSS Database error :\n$log"); } print WRITER "$log"; } close(READER); close(WRITER); # On supprime le fichier de log temporaire if ( -e $logFileTmp ) { unlink ($logFileTmp); } } } # On lance le programme de restriction des ACs if($noRCA == 1) { foreach (@lstArgs) { next if (! -d "$_->{nssFile}" or ! -e "$_->{caPolicy}"); my $logFileTmp = $logFile.rand(); system("$nssRestrictCa $builtIn \"$_->{nssFile}\" \"$_->{caPolicy}\" 2>&1 >> $logFileTmp"); open(READER,"< ".$logFileTmp) || die ("Error : unable to open temp log file !\n"); open(WRITER,">> ".$logFile) || die ("Error : unable to open log file !\n"); # On parcourt le fichier de log temporaire afin de vérifier si l'on doit rediriger une erreur vers la sortie std (afin d'envoyer un mail de notification via cron) while (my $log = ) { # Si une erreur commence par un # on l'écrit sur la sortie std if( $log =~ s/^\s*#//g) { print("NSS Database error :\n$log"); } print WRITER "$log"; } close(READER); close(WRITER); # On supprime le fichier de log temporaire if ( -e $logFileTmp ) { unlink ($logFileTmp); } } } close(WRITER);