Fix c_rehash script, add -fingerprint option to crl.

This commit is contained in:
Dr. Stephen Henson 2000-05-18 00:33:00 +00:00
parent 0d3b0afe9e
commit 439df5087f
8 changed files with 196 additions and 59 deletions

View File

@ -4,6 +4,12 @@
Changes between 0.9.5a and 0.9.6 [xx XXX 2000]
*) Enhance c_rehash script. Old version would mishandle certificates
with the same subject name hash and wouldn't handle CRLs at all.
Added -fingerprint option to crl utility, to support new c_rehash
features.
[Steve Henson]
*) Eliminate non-ANSI declarations in crypto.h and stack.h.
[Ulf Möller]

View File

@ -890,12 +890,13 @@ EOF
### (system 'make depend') == 0 or exit $? if $depflags ne "";
# Run "make depend" manually if you want to be able to delete
# the source code files of ciphers you left out.
&dofile("tools/c_rehash",$openssldir,'^DIR=', 'DIR=%s',);
if ( $perl =~ m@^/@) {
&dofile("tools/c_rehash",$perl,'^#!/', '#!%s','^my \$dir;$', 'my $dir = "' . $openssldir . '";');
&dofile("apps/der_chop",$perl,'^#!/', '#!%s');
&dofile("apps/CA.pl",$perl,'^#!/', '#!%s');
} else {
# No path for Perl known ...
&dofile("tools/c_rehash",'/usr/local/bin/perl','^#!/', '#!%s','^my \$dir;$', 'my $dir = "' . $openssldir . '";');
&dofile("apps/der_chop",'/usr/local/bin/perl','^#!/', '#!%s');
&dofile("apps/CA.pl",'/usr/local/bin/perl','^#!/', '#!%s');
}

View File

@ -262,7 +262,7 @@ dclean:
rehash: rehash.time
rehash.time: certs
@(OPENSSL="`pwd`/apps/openssl"; export OPENSSL; sh tools/c_rehash certs)
@(OPENSSL="`pwd`/apps/openssl"; export OPENSSL; $(PERL) tools/c_rehash certs)
touch rehash.time
test: tests

View File

@ -135,7 +135,7 @@ $(DLIBCRYPTO):
$(PROGRAM): progs.h $(E_OBJ) $(PROGRAM).o $(DLIBCRYPTO) $(DLIBSSL)
$(RM) $(PROGRAM)
$(CC) -o $(PROGRAM) $(CFLAGS) $(PROGRAM).o $(E_OBJ) $(PEX_LIBS) $(LIBSSL) $(LIBCRYPTO) $(EX_LIBS)
@(cd ..; OPENSSL="`pwd`/apps/openssl"; export OPENSSL; sh tools/c_rehash certs)
@(cd ..; OPENSSL="`pwd`/apps/openssl"; export OPENSSL; $(PERL) tools/c_rehash certs)
progs.h: progs.pl
$(PERL) progs.pl $(E_EXE) >progs.h

View File

@ -104,6 +104,7 @@ int MAIN(int argc, char **argv)
int informat,outformat;
char *infile=NULL,*outfile=NULL;
int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0;
int fingerprint = 0;
char **pp,buf[256];
X509_STORE *store = NULL;
X509_STORE_CTX ctx;
@ -111,6 +112,7 @@ int MAIN(int argc, char **argv)
X509_OBJECT xobj;
EVP_PKEY *pkey;
int do_ver = 0;
const EVP_MD *md_alg,*digest=EVP_md5();
apps_startup();
@ -183,6 +185,13 @@ int MAIN(int argc, char **argv)
nextupdate= ++num;
else if (strcmp(*argv,"-noout") == 0)
noout= ++num;
else if (strcmp(*argv,"-fingerprint") == 0)
fingerprint= ++num;
else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
{
/* ok */
digest=md_alg;
}
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
@ -274,6 +283,26 @@ bad:
BIO_printf(bio_out,"NONE");
BIO_printf(bio_out,"\n");
}
if (fingerprint == i)
{
int j;
unsigned int n;
unsigned char md[EVP_MAX_MD_SIZE];
if (!X509_CRL_digest(x,digest,md,&n))
{
BIO_printf(bio_err,"out of memory\n");
goto end;
}
BIO_printf(bio_out,"%s Fingerprint=",
OBJ_nid2sn(EVP_MD_type(digest)));
for (j=0; j<(int)n; j++)
{
BIO_printf(bio_out,"%02X%c",md[j],
(j+1 == (int)n)
?'\n':':');
}
}
}
}

View File

@ -660,6 +660,8 @@ int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
int X509_digest(X509 *data,const EVP_MD *type,unsigned char *md,unsigned int *len);
int X509_CRL_digest(X509_CRL *data,const EVP_MD *type,unsigned char *md,unsigned int *len);
int X509_REQ_digest(X509_REQ *data,const EVP_MD *type,unsigned char *md,unsigned int *len);
int X509_NAME_digest(X509_NAME *data,const EVP_MD *type,
unsigned char *md,unsigned int *len);
#endif

View File

@ -417,6 +417,18 @@ int X509_digest(X509 *data, const EVP_MD *type, unsigned char *md,
return(ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len));
}
int X509_CRL_digest(X509_CRL *data, const EVP_MD *type, unsigned char *md,
unsigned int *len)
{
return(ASN1_digest((int (*)())i2d_X509_CRL,type,(char *)data,md,len));
}
int X509_REQ_digest(X509_REQ *data, const EVP_MD *type, unsigned char *md,
unsigned int *len)
{
return(ASN1_digest((int (*)())i2d_X509_REQ,type,(char *)data,md,len));
}
int X509_NAME_digest(X509_NAME *data, const EVP_MD *type, unsigned char *md,
unsigned int *len)
{

View File

@ -1,61 +1,148 @@
#!/bin/sh
#
# redo the hashes for the certificates in your cert path or the ones passed
# on the command line.
#
#!/usr/local/bin/perl
if [ "$OPENSSL"x = "x" -o ! -x "$OPENSSL" ]; then
OPENSSL='openssl'
export OPENSSL
fi
DIR=/usr/local/ssl
PATH=$DIR/bin:$PATH
if [ ! -f "$OPENSSL" ]; then
found=0
for dir in . `echo $PATH | sed -e 's/:/ /g'`; do
if [ -f "$dir/$OPENSSL" ]; then
found=1
break
fi
done
if [ $found = 0 ]; then
echo "c_rehash: rehashing skipped ('openssl' program not available)" 1>&2
exit 0
fi
fi
# Perl c_rehash script, scan all files in a directory
# and add symbolic links to their hash values.
SSL_DIR=$DIR/certs
my $openssl;
if [ "$*" = "" ]; then
CERTS=${*:-${SSL_CERT_DIR:-$SSL_DIR}}
else
CERTS=$*
fi
my $dir;
if(defined $ENV{OPENSSL}) {
$openssl = $ENV{OPENSSL};
} else {
$openssl = "openssl";
$ENV{OPENSSL} = $openssl;
}
$ENV{PATH} .= ":$dir/bin";
if(! -f $openssl) {
my $found = 0;
foreach (split /:/, $ENV{PATH}) {
if(-f "$_/$openssl") {
$found = 1;
last;
}
}
if($found == 0) {
print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n";
exit 0;
}
}
if(@ARGV) {
@dirlist = @ARGV;
} elsif($ENV{SSL_CERT_DIR}) {
@dirlist = split /:/, $ENV{SSL_CERT_DIR};
} else {
$dirlist[0] = "$dir/certs";
}
foreach (@dirlist) {
if(-d $_ and -w $_) {
hash_dir($_);
}
}
sub hash_dir {
my %hashlist;
print "Doing $_[0]\n";
chdir $_[0];
opendir(DIR, ".");
my @flist = readdir(DIR);
# Delete any existing symbolic links
foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
if(-l $_) {
unlink $_;
}
}
closedir DIR;
FILE: foreach $fname (grep {/\.pem$/} @flist) {
# Check to see if certificates and/or CRLs present.
my ($cert, $crl) = check_file($fname);
if(!$cert && !$crl) {
print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
next;
}
link_hash_cert($fname) if($cert);
link_hash_crl($fname) if($crl);
}
}
sub check_file {
my ($is_cert, $is_crl) = (0,0);
my $fname = $_[0];
open IN, $fname;
while(<IN>) {
if(/^-----BEGIN (.*)-----/) {
my $hdr = $1;
if($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
$is_cert = 1;
last if($is_crl);
} elsif($hdr eq "X509 CRL") {
$is_crl = 1;
last if($is_cert);
}
}
}
close IN;
return ($is_cert, $is_crl);
}
# Link a certificate to its subject name hash value, each hash is of
# the form <hash>.<n> where n is an integer. If the hash value already exists
# then we need to up the value of n, unless its a duplicate in which
# case we skip the link. We check for duplicates by comparing the
# certificate fingerprints
sub link_hash_cert {
my $fname = $_[0];
my ($hash, $fprint) = `$openssl x509 -hash -fingerprint -noout -in $fname`;
chomp $hash;
chomp $fprint;
$fprint =~ s/^.*=//;
$fprint =~ tr/://d;
my $suffix = 0;
# Search for an unused hash filename
while(exists $hashlist{"$hash.$suffix"}) {
# Hash matches: if fingerprint matches its a duplicate cert
if($hashlist{"$hash.$suffix"} eq $fprint) {
print STDERR "WARNING: Skipping duplicate certificate $fname\n";
return;
}
$suffix++;
}
$hash .= ".$suffix";
print "$fname => $hash\n";
symlink $fname, $hash;
$hashlist{$hash} = $fprint;
}
# Same as above except for a CRL. CRL links are of the form <hash>.r<n>
sub link_hash_crl {
my $fname = $_[0];
my ($hash, $fprint) = `$openssl crl -hash -fingerprint -noout -in $fname`;
chomp $hash;
chomp $fprint;
$fprint =~ s/^.*=//;
$fprint =~ tr/://d;
my $suffix = 0;
# Search for an unused hash filename
while(exists $hashlist{"$hash.r$suffix"}) {
# Hash matches: if fingerprint matches its a duplicate cert
if($hashlist{"$hash.r$suffix"} eq $fprint) {
print STDERR "WARNING: Skipping duplicate CRL $fname\n";
return;
}
$suffix++;
}
$hash .= ".r$suffix";
print "$fname => $hash\n";
symlink $fname, $hash;
$hashlist{$hash} = $fprint;
}
IFS=': '
for i in $CERTS
do
(
IFS=' '
if [ -d $i -a -w $i ]; then
cd $i
echo "Doing $i"
for i in *.pem
do
if [ $i != '*.pem' ]; then
h=`$OPENSSL x509 -hash -noout -in $i`
if [ "x$h" = "x" ]; then
echo $i does not contain a certificate
else
if [ -f $h.0 ]; then
/bin/rm -f $h.0
fi
echo "$i => $h.0"
ln -s $i $h.0
fi
fi
done
fi
)
done