Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
#!/usr/bin/perl
#
# Wrapper around the ca to make it easier to use
#
use strict;
use warnings;
use File::Copy;
our ($ME) = ($0 =~ m|/([^/]+)$|);
our $openssl = "openssl";
if(defined $ENV{'OPENSSL'}) {
$openssl = $ENV{'OPENSSL'};
} else {
$ENV{'OPENSSL'} = $openssl;
}
our $verbose = 1;
our $OPENSSL_CONFIG = defined $ENV{'OPENSSL_CONFIG'} ? $ENV{'OPENSSL_CONFIG'} : "";
our $OPENSSL_CONFIG_WEBCLIENT = "-config /etc/pki/tls/openssl-webclient.cnf";
our $CERTTOP = defined $ENV{'CERTTOP'} ? $ENV{'CERTTOP'} : "/etc/pki/webclient";
our $DAYS = "-days 730";
our $CADAYS = "-days 3650";
our $REQ = "$openssl req";
our $CA = "$openssl ca";
our $VERIFY = "$openssl verify";
our $X509 = "$openssl x509";
our $PKCS12 = "$openssl pkcs12";
our $CNAMETXT = "My Certificate";
our $PASSOPT;
# default openssl.cnf file has setup as per the following
our $CATOP = defined $ENV{'CATOP'} ? $ENV{'CATOP'} : "/etc/pki/CA";
our $CAKEY = "cakey.pem";
our $CAREQ = "careq.pem";
our $CACERT = "cacert.pem";
our $CACRL = "crl.pem";
our $DIRMODE = 0755;
our $NEWKEY = "newkey.key";
our $NEWREQ = "newreq.pem";
our $NEWCERT = "newcert.pem";
our $NEWP12 = "newcert.p12";
our $RET = 0;
our $WHAT = shift @ARGV;
our $FILE;
sub help
{
print STDERR "usage: $ME -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n";
print STDERR " $ME -pkcs12 [certname]\n";
print STDERR " $ME -crl|-revoke cert-filename [reason]\n";
print STDERR " $ME -newwebclient client-name [certname]\n";
print STDERR " $ME -revoke-webclient client-name [reason]\n";
}
# See if reason for a CRL entry is valid; exit if not.
sub crl_reason_ok
{
my $r = shift;
if ($r eq 'unspecified' || $r eq 'keyCompromise'
|| $r eq 'CACompromise' || $r eq 'affiliationChanged'
|| $r eq 'superseded' || $r eq 'cessationOfOperation'
|| $r eq 'certificateHold' || $r eq 'removeFromCRL') {
return 1;
}
print STDERR "Invalid CRL reason; must be one of:\n";
print STDERR " unspecified, keyCompromise, CACompromise,\n";
print STDERR " affiliationChanged, superseded, cessationOfOperation\n";
print STDERR " certificateHold, removeFromCRL";
exit 1;
}
# Copy a PEM-format file; return like exit status (zero means ok)
sub copy_pemfile
{
my ($infile, $outfile, $bound) = @_;
my $found = 0;
open IN, $infile || die "Cannot open $infile, $!";
open OUT, ">$outfile" || die "Cannot write to $outfile, $!";
while () {
$found = 1 if /^-----BEGIN.*$bound/;
print OUT $_ if $found;
$found = 2, last if /^-----END.*$bound/;
}
close IN;
close OUT;
return $found == 2 ? 0 : 1;
}
# Wrapper around system; useful for debugging. Returns just the exit status
sub run
{
my $cmd = shift;
print "====\n$cmd\n" if $verbose;
my $status = system($cmd);
print "==> $status\n====\n" if $verbose;
return $status >> 8;
}
# Create a certificate
sub newcert
{
$RET = run("$REQ $OPENSSL_CONFIG -new -x509"
. " -keyout $NEWKEY -out $NEWCERT $DAYS");
print "Cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0;
}
# Create a certificate request along with a private key
sub newreq
{
$RET = run("$REQ $OPENSSL_CONFIG -new -keyout $NEWKEY -out $NEWREQ $DAYS");
print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0;
}
# Create a certificate request with an unencrypted key
sub newreq_nodes
{
$RET = run("$REQ $OPENSSL_CONFIG -new -nodes"
. " -keyout $NEWKEY -out $NEWREQ $DAYS");
print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0;
}
# Build a certificate authority(CA)
sub newca
{
# create the directory hierarchy
unless (-d "$CATOP") {
mkdir ${CATOP}, $DIRMODE;
mkdir "${CATOP}/certs", $DIRMODE;
mkdir "${CATOP}/crl", $DIRMODE ;
mkdir "${CATOP}/newcerts", $DIRMODE;
mkdir "${CATOP}/private", $DIRMODE;
}
open OUT, ">${CATOP}/index.txt";
close OUT;
open OUT, ">${CATOP}/crlnumber";
print OUT "01\n";
close OUT;
# ask user for existing CA certificate
print "CA certificate filename (or enter to create)\n";
$FILE = "" unless defined($FILE = );
$FILE =~ s{\R$}{};
if ($FILE ne "") {
copy_pemfile($FILE,"${CATOP}/private/$CAKEY", "PRIVATE");
copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE");
} else {
print "Making CA certificate ...\n";
$RET = run("$REQ $OPENSSL_CONFIG -new -keyout"
. " ${CATOP}/private/$CAKEY"
. " -out ${CATOP}/$CAREQ");
$RET = run("$CA $OPENSSL_CONFIG -create_serial"
. " -out ${CATOP}/$CACERT $CADAYS -batch"
. " -keyfile ${CATOP}/private/$CAKEY -selfsign"
. " -extensions v3_ca"
. " -infiles ${CATOP}/$CAREQ") if $RET == 0;
print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0;
}
}
# Create a PKCS#12 file from the signed cert and key
sub pkcs12
{
my $cname = shift;
$cname = "$CNAMETXT" unless $cname;
$RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY"
. " -certfile ${CATOP}/$CACERT"
. " -out $NEWP12 $PASSOPT"
. " -export -name \"$cname\"");
print "PKCS#12 file is in $NEWP12\n" if $RET == 0;
}
# Sign a certificate based on a certificate request
sub xsign
{
$RET = run("$CA $OPENSSL_CONFIG -policy policy_anything"
. " -infiles $NEWREQ");
}
# Same as above except the certificate is writen to STDOUT
sub sign
{
$RET = run("$CA $OPENSSL_CONFIG -policy policy_anything"
. " -out $NEWCERT -infiles $NEWREQ");
print "Signed certificate is in $NEWCERT\n" if $RET == 0;
}
# Same as sign except it uses configuration file section v3_ca
sub signCA
{
$RET = run("$CA $OPENSSL_CONFIG -policy policy_anything"
. " -out $NEWCERT -extensions v3_ca -infiles $NEWREQ");
print "Signed CA certificate is in $NEWCERT\n" if $RET == 0;
}
# Same as sign except it expects a self signed certificate present in newreq.pem
sub signcert
{
$RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ"
. " -out tmp.pem");
$RET = run("$CA $OPENSSL_CONFIG -policy policy_anything -out $NEWCERT"
. " -infiles tmp.pem") if $RET == 0;
print "Signed certificate is in $NEWCERT\n" if $RET == 0;
}
# Verify certificates against CA certificate for CATOP
sub verify
{
my @files = @ARGV ? @ARGV : ( $NEWCERT );
my $file;
foreach $file (@files) {
my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file");
$RET = $status if $status != 0;
}
}
# Create a cert/key pair and PKCS#12
sub newwebclient
{
$OPENSSL_CONFIG = $OPENSSL_CONFIG_WEBCLIENT unless $OPENSSL_CONFIG;
my ($cname,$cnametxt) = @_;
unless ($cname) {
print STDERR "Certificate name is required.\n";
exit 1;
}
$cnametxt = "$CNAMETXT" unless $cnametxt;
# create the directory hierarchy
unless (-d "$CERTTOP") {
mkdir ${CERTTOP}, $DIRMODE;
mkdir "${CERTTOP}/certs", $DIRMODE;
mkdir "${CERTTOP}/newcerts", $DIRMODE;
mkdir "${CERTTOP}/private", $DIRMODE;
}
if (-f "${CERTTOP}/certs/${cname}.pem") {
print STDERR "Certificate file ${cname}.pem already exists!\n"
. "Please run \'$ME -revoke-webclient $cname\' and then try again\n";
exit 1;
}
chdir "${CERTTOP}/newcerts";
# create a certificate request with a private key
newreq_nodes();
if ($RET != 0) {
print STDERR "Request (and private key) generation failed\n";
exit 1;
}
$RET = run("$CA $OPENSSL_CONFIG -out $NEWCERT $DAYS"
. " -infiles $NEWREQ");
if ($RET != 0 || ! -f $NEWCERT || -z $NEWCERT) {
print STDERR "Signing of certificate failed\n";
exit 1;
}
print "Signed certificate is in $NEWCERT\n";
if (-f "${CERTTOP}/private/exportpw") {
$PASSOPT="-passout file:${CERTTOP}/private/exportpw";
}
# create a PKCS#12 file from the signed cert and key
pkcs12($cnametxt);
if ($RET != 0) {
print STDERR "Creation of PKCS#12 failed\n";
exit 1;
}
# tidy up the keys
move($NEWP12,"${CERTTOP}/private/${cname}.p12");
move($NEWKEY,"${CERTTOP}/private/${cname}.key");
move($NEWCERT,"${CERTTOP}/certs/${cname}.pem");
unlink $NEWREQ;
my $msg = <<"EOM";
Keys generated successfully:
${CERTTOP}/certs/${cname}.pem public key(signed)
${CERTTOP}/private/${cname}.key private key
${CERTTOP}/private/${cname}.p12 PKCS#12(the bag of above two)
${CATOP}/cacert.crt Private-CA public key
EOM
print $msg. "\n";
}
# Update Certificate Revocation List
sub gencrl
{
$RET = run("$CA $OPENSSL_CONFIG -gencrl -out ${CATOP}/crl/$CACRL");
if ($RET != 0) {
print STDERR "Failed to Generated CRL\n";
exit 1;
}
print "Generated CRL is in ${CATOP}/crl/$CACRL\n";
# Place what to do after CRL update, e.g.
# $RET = run("cd ${CERTTOP} && make");
}
# Revoke a certificate
sub revoke
{
# revoke a certificate
my ($cname,$reason) = @_;
unless ($cname) {
print "Certificate filename is required; reason optional.\n";
exit 1;
}
$reason = "" unless defined $reason;
if (length($reason) gt 0 && crl_reason_ok($reason)) {
$reason = " -crl_reason $reason"
}
unless (-f "$cname") {
print STDERR "No such file $cname\n";
exit 1;
}
$RET = run("$CA $OPENSSL_CONFIG -revoke \"$cname\"" . $reason);
if ($RET != 0) {
print STDERR "Failed to revoke $cname\n";
exit 1;
}
}
# Revoke and delete a set of cert, key and PKCS#12 files
sub revoke_webclient
{
$OPENSSL_CONFIG = $OPENSSL_CONFIG_WEBCLIENT unless $OPENSSL_CONFIG;
my ($cname,$reason) = @_;
unless ($cname) {
print "Certificate name is required; reason optional.\n";
exit 1;
}
$reason = "" unless defined $reason;
unless (-f "${CERTTOP}/certs/${cname}.pem") {
print STDERR "No such file ${cname}.pem\n";
exit 1;
}
revoke("${CERTTOP}/certs/${cname}.pem",$reason);
# remove the revoked key set
run("rm -i ${CERTTOP}/certs/${cname}.pem");
run("rm -i ${CERTTOP}/private/${cname}.key");
run("rm -i ${CERTTOP}/private/${cname}.p12");
print "cname $cname successfully revoked.\n";
gencrl();
}
unless ($WHAT) {
help();
exit 0;
}
if ( $WHAT =~ /^(-\?|-h|-help)$/ ) {
help();
exit 0;
}
if ($WHAT eq '-newcert' ) {
} elsif ($WHAT eq '-newreq' ) {
newreq();
} elsif ($WHAT eq '-newreq-nodes' ) {
newreq_nodes();
} elsif ($WHAT eq '-newca' ) {
newca();
} elsif ($WHAT eq '-pkcs12' ) {
pkcs12($ARGV[0]);
} elsif ($WHAT eq '-xsign' ) {
xsign();
} elsif ($WHAT eq '-sign' ) {
sign();
} elsif ($WHAT eq '-signCA' ) {
signCA();
} elsif ($WHAT eq '-signcert' ) {
signcert();
} elsif ($WHAT eq '-verify' ) {
verify();
} elsif ($WHAT eq '-newwebclient' ) {
newwebclient($ARGV[0],$ARGV[1]);
} elsif ($WHAT eq '-crl' ) {
gencrl();
} elsif ($WHAT eq '-revoke' ) {
revoke($ARGV[0],$ARGV[1]);
} elsif ($WHAT eq '-revoke-webclient' ) {
revoke_webclient($ARGV[0],$ARGV[1]);
} else {
print STDERR "Unknown arg \"$WHAT\"\n";
print STDERR "Use -help for help.\n";
exit 1;
}
exit $RET;