Commit 56a47ccc authored by Leigh B Stoller's avatar Leigh B Stoller

Companion change to httpd.conf change; ssl client verification is now

"optional" in the server, so we have to check more carefully in the
script that the client supplied a proper certificate.

Also, the server is now exporting the entire client certificate so
that we can pull out the URN from it. UUIDs are slowly being phased
out. This change requires some new ports installed on boss:

 "p5-Crypt-OpenSSL-X509" => "/usr/ports/security/p5-Crypt-OpenSSL-X509",
 "p5-Crypt-X509"         => "/usr/ports/security/p5-Crypt-X509"
parent 741be49b
......@@ -15,6 +15,8 @@ use English;
use Frontier::Responder;
use Data::Dumper;
use POSIX;
use Crypt::X509;
use Crypt::OpenSSL::X509;
# Yack. apache does not close fds before the exec, and if this dies
# we are left with a giant mess.
......@@ -26,11 +28,15 @@ BEGIN {
}
# Do this early so that we talk to the right DB.
use vars qw($GENI_DBNAME $GENI_ISCLRHOUSE);
use vars qw($GENI_DBNAME $GENI_ISCLRHOUSE $GENI_CHPEMFILE);
BEGIN { $GENI_DBNAME = "geni-ch"; $GENI_ISCLRHOUSE = 1; }
# Configure variables
my $EMULAB_PEMFILE = "@prefix@/etc/genich.pem";
my $ETCDIR = "@prefix@/etc";
my $EMULAB_PEMFILE = ((-s "$ETCDIR/genich-local.pem") ?
"$ETCDIR/genich-local.pem" : "$ETCDIR/genich.pem");
# See GeniCredential; a helpful debugging aid.
$GENI_CHPEMFILE = $EMULAB_PEMFILE;
# Testbed libraries.
use lib '@prefix@/lib';
......@@ -63,6 +69,24 @@ if (!defined($certificate)) {
" Could not get uuid from $EMULAB_PEMFILE\n");
}
$ENV{'MYUUID'} = $certificate->uuid();
# The URN could also come from the certificate, and that might be preferable
# in some ways (if anybody is doing something silly like authenticating
# with somebody else's certificate). But that would require everybody to
# upgrade to URNs in their certificates, so we can't assume it yet.
$ENV{'MYURN'} = "urn:publicid:IDN+@OURDOMAIN@+authority+ch";
#
# Helper function to return a properly formated XML error.
#
sub XMLError($$)
{
my ($code, $string) = @_;
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault($code, $string);
exit(0);
}
#
# Make sure the client presented a valid certificate that apache says
......@@ -77,10 +101,7 @@ $ENV{'MYUUID'} = $certificate->uuid();
#
if (! (exists($ENV{'SSL_CLIENT_VERIFY'}) &&
$ENV{'SSL_CLIENT_VERIFY'} eq "SUCCESS")) {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid or missing certificate");
exit(0);
XMLError(-1, "Invalid or missing certificate");
}
#
......@@ -116,11 +137,34 @@ if (exists($ENV{'SSL_CLIENT_S_DN_CN'}) &&
$ENV{'GENIUUID'} = $ENV{'SSL_CLIENT_S_DN_CN'};
}
else {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid certificate; no UUID");
exit(0);
XMLError(-1, "Invalid certificate; no UUID");
}
#
# The CERT data from apache holds the URN of the caller.
#
if (exists($ENV{'SSL_CLIENT_CERT'})) {
my $x509 = eval {
Crypt::OpenSSL::X509->new_from_string($ENV{'SSL_CLIENT_CERT'}); };
if ($@) {
XMLError(-1, "Invalid certificate: $@");
}
my $cert = $x509->as_string(Crypt::OpenSSL::X509::FORMAT_ASN1);
XMLError(-1, "Could not convert certificate to ASN1")
if (!defined($cert) || $cert eq '');
my $decoded = Crypt::X509->new( cert => $cert );
if ($decoded->error) {
XMLError(-1, "Error decoding certificate:" . $decoded->error);
}
foreach my $tmp (@{ $decoded->SubjectAltName }) {
if ($tmp =~ /^uniformResourceIdentifier=(.*)$/) {
$ENV{'GENIURN'} = $1;
}
}
}
XMLError(-1, "Invalid authentication certificate; no URN. Please regenerate.")
if (!exists($ENV{'GENIURN'}));
#
# Reaching into the Frontier code so I can debug this crap.
#
......
......@@ -16,12 +16,14 @@ use Frontier::Responder;
use Frontier::RPC2;
use Data::Dumper;
use POSIX;
use Crypt::X509;
use Crypt::OpenSSL::X509;
# Yack. apache does not close fds before the exec, and if this dies
# we are left with a giant mess.
BEGIN {
no warnings;
for (my $i = 3; $i < 2048; $i++) {
for (my $i = 3; $i < 1024; $i++) {
POSIX:close($i);
}
}
......@@ -79,6 +81,19 @@ $ENV{'MYUUID'} = $certificate->uuid();
# upgrade to URNs in their certificates, so we can't assume it yet.
$ENV{'MYURN'} = "urn:publicid:IDN+@OURDOMAIN@+authority+cm";
#
# Helper function to return a properly formated XML error.
#
sub XMLError($$)
{
my ($code, $string) = @_;
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault($code, $string);
exit(0);
}
#
# Make sure the client presented a valid certificate that apache says
# is okay.
......@@ -92,10 +107,7 @@ $ENV{'MYURN'} = "urn:publicid:IDN+@OURDOMAIN@+authority+cm";
#
if (! (exists($ENV{'SSL_CLIENT_VERIFY'}) &&
$ENV{'SSL_CLIENT_VERIFY'} eq "SUCCESS")) {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid or missing certificate");
exit(0);
XMLError(-1, "Invalid or missing certificate");
}
#
......@@ -131,11 +143,34 @@ if (exists($ENV{'SSL_CLIENT_S_DN_CN'}) &&
$ENV{'GENIUUID'} = $ENV{'SSL_CLIENT_S_DN_CN'};
}
else {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid certificate; no UUID");
exit(0);
XMLError(-1, "Invalid certificate; no UUID");
}
#
# The CERT data from apache holds the URN of the caller.
#
if (exists($ENV{'SSL_CLIENT_CERT'})) {
my $x509 = eval {
Crypt::OpenSSL::X509->new_from_string($ENV{'SSL_CLIENT_CERT'}); };
if ($@) {
XMLError(-1, "Invalid certificate: $@");
}
my $cert = $x509->as_string(Crypt::OpenSSL::X509::FORMAT_ASN1);
XMLError(-1, "Could not convert certificate to ASN1")
if (!defined($cert) || $cert eq '');
my $decoded = Crypt::X509->new( cert => $cert );
if ($decoded->error) {
XMLError(-1, "Error decoding certificate:" . $decoded->error);
}
foreach my $tmp (@{ $decoded->SubjectAltName }) {
if ($tmp =~ /^uniformResourceIdentifier=(.*)$/) {
$ENV{'GENIURN'} = $1;
}
}
}
XMLError(-1, "Invalid authentication certificate; no URN. Please regenerate.")
if (!exists($ENV{'GENIURN'}));
#
# Reaching into the Frontier code so I can debug this crap.
#
......
......@@ -15,12 +15,14 @@ use English;
use Frontier::Responder;
use Data::Dumper;
use POSIX;
use Crypt::X509;
use Crypt::OpenSSL::X509;
# Yack. apache does not close fds before the exec, and if this dies
# we are left with a giant mess.
BEGIN {
no warnings;
for (my $i = 3; $i < 2048; $i++) {
for (my $i = 3; $i < 1024; $i++) {
POSIX:close($i);
}
}
......@@ -67,6 +69,24 @@ if (!defined($certificate)) {
" Could not get uuid from $EMULAB_PEMFILE\n");
}
$ENV{'MYUUID'} = $certificate->uuid();
# The URN could also come from the certificate, and that might be preferable
# in some ways (if anybody is doing something silly like authenticating
# with somebody else's certificate). But that would require everybody to
# upgrade to URNs in their certificates, so we can't assume it yet.
$ENV{'MYURN'} = "urn:publicid:IDN+@OURDOMAIN@+authority+sa";
#
# Helper function to return a properly formated XML error.
#
sub XMLError($$)
{
my ($code, $string) = @_;
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault($code, $string);
exit(0);
}
#
# Make sure the client presented a valid certificate that apache says
......@@ -81,10 +101,7 @@ $ENV{'MYUUID'} = $certificate->uuid();
#
if (! (exists($ENV{'SSL_CLIENT_VERIFY'}) &&
$ENV{'SSL_CLIENT_VERIFY'} eq "SUCCESS")) {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid or missing certificate");
exit(0);
XMLError(-1, "Invalid or missing certificate");
}
#
......@@ -120,11 +137,34 @@ if (exists($ENV{'SSL_CLIENT_S_DN_CN'}) &&
$ENV{'GENIUUID'} = $ENV{'SSL_CLIENT_S_DN_CN'};
}
else {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid certificate; no UUID");
exit(0);
XMLError(-1, "Invalid certificate; no UUID");
}
#
# The CERT data from apache holds the URN of the caller.
#
if (exists($ENV{'SSL_CLIENT_CERT'})) {
my $x509 = eval {
Crypt::OpenSSL::X509->new_from_string($ENV{'SSL_CLIENT_CERT'}); };
if ($@) {
XMLError(-1, "Invalid certificate: $@");
}
my $cert = $x509->as_string(Crypt::OpenSSL::X509::FORMAT_ASN1);
XMLError(-1, "Could not convert certificate to ASN1")
if (!defined($cert) || $cert eq '');
my $decoded = Crypt::X509->new( cert => $cert );
if ($decoded->error) {
XMLError(-1, "Error decoding certificate:" . $decoded->error);
}
foreach my $tmp (@{ $decoded->SubjectAltName }) {
if ($tmp =~ /^uniformResourceIdentifier=(.*)$/) {
$ENV{'GENIURN'} = $1;
}
}
}
XMLError(-1, "Invalid authentication certificate; no URN. Please regenerate.")
if (!exists($ENV{'GENIURN'}));
#
# Reaching into the Frontier code so I can debug this crap.
#
......
......@@ -15,6 +15,8 @@ use English;
use Frontier::Responder;
use Data::Dumper;
use POSIX;
use Crypt::X509;
use Crypt::OpenSSL::X509;
# Yack. apache does not close fds before the exec, and if this dies
# we are left with a giant mess.
......@@ -64,6 +66,24 @@ if (!defined($certificate)) {
" Could not get uuid from $EMULAB_PEMFILE\n");
}
$ENV{'MYUUID'} = $certificate->uuid();
# The URN could also come from the certificate, and that might be preferable
# in some ways (if anybody is doing something silly like authenticating
# with somebody else's certificate). But that would require everybody to
# upgrade to URNs in their certificates, so we can't assume it yet.
$ENV{'MYURN'} = "urn:publicid:IDN+@OURDOMAIN@+authority+ses";
#
# Helper function to return a properly formated XML error.
#
sub XMLError($$)
{
my ($code, $string) = @_;
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault($code, $string);
exit(0);
}
#
# Make sure the client presented a valid certificate that apache says
......@@ -78,10 +98,7 @@ $ENV{'MYUUID'} = $certificate->uuid();
#
if (! (exists($ENV{'SSL_CLIENT_VERIFY'}) &&
$ENV{'SSL_CLIENT_VERIFY'} eq "SUCCESS")) {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid or missing certificate");
exit(0);
XMLError(-1, "Invalid or missing certificate");
}
#
......@@ -117,11 +134,34 @@ if (exists($ENV{'SSL_CLIENT_S_DN_CN'}) &&
$ENV{'GENIUUID'} = $ENV{'SSL_CLIENT_S_DN_CN'};
}
else {
my $decoder = Frontier::RPC2->new();
print "Content-Type: text/xml \n\n";
print $decoder->encode_fault(-1, "Invalid certificate; no UUID");
exit(0);
XMLError(-1, "Invalid certificate; no UUID");
}
#
# The CERT data from apache holds the URN of the caller.
#
if (exists($ENV{'SSL_CLIENT_CERT'})) {
my $x509 = eval {
Crypt::OpenSSL::X509->new_from_string($ENV{'SSL_CLIENT_CERT'}); };
if ($@) {
XMLError(-1, "Invalid certificate: $@");
}
my $cert = $x509->as_string(Crypt::OpenSSL::X509::FORMAT_ASN1);
XMLError(-1, "Could not convert certificate to ASN1")
if (!defined($cert) || $cert eq '');
my $decoded = Crypt::X509->new( cert => $cert );
if ($decoded->error) {
XMLError(-1, "Error decoding certificate:" . $decoded->error);
}
foreach my $tmp (@{ $decoded->SubjectAltName }) {
if ($tmp =~ /^uniformResourceIdentifier=(.*)$/) {
$ENV{'GENIURN'} = $1;
}
}
}
XMLError(-1, "Invalid authentication certificate; no URN. Please regenerate.")
if (!exists($ENV{'GENIURN'}));
#
# Reaching into the Frontier code so I can debug this crap.
#
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment