From cb5d57a1f369449e6e6f9125e952545a899f8e71 Mon Sep 17 00:00:00 2001 From: Chris Andrews Date: Nov 29 2010 14:47:49 +0000 Subject: Improve cert verification in the SOAP binding. --- diff --git a/lib/Net/SAML2/Binding/SOAP.pm b/lib/Net/SAML2/Binding/SOAP.pm index edffe4b..ca7b5ea 100644 --- a/lib/Net/SAML2/Binding/SOAP.pm +++ b/lib/Net/SAML2/Binding/SOAP.pm @@ -49,6 +49,7 @@ has 'url' => (isa => Uri, is => 'ro', required => 1, coerce => 1); has 'key' => (isa => Str, is => 'ro', required => 1); has 'cert' => (isa => Str, is => 'ro', required => 1); has 'idp_cert' => (isa => Str, is => 'ro', required => 1); +has 'cacert' => (isa => Str, is => 'ro', required => 1); =head2 request($message) @@ -88,17 +89,25 @@ sub handle_response { my ($self, $response) = @_; # verify the response - my $sig_verify = XML::Sig->new({ x509 => 1, cert_text => $self->idp_cert }); - my $ret = $sig_verify->verify($response); + my $x = XML::Sig->new({ x509 => 1, cert_text => $self->idp_cert }); + my $ret = $x->verify($response); die "bad SOAP response" unless $ret; + # verify the signing certificate + my $cert = $x->signer_cert; + my $ca = Crypt::OpenSSL::VerifyX509->new($self->cacert); + $ret = $ca->verify($cert); + die "bad signer cert" unless $ret; + + my $subject = sprintf("%s (verified)", $cert->subject); + # parse the SOAP response and return the payload my $parser = XML::XPath->new( xml => $response ); $parser->set_namespace('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/'); $parser->set_namespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol'); my $saml = $parser->findnodes_as_string('/soap-env:Envelope/soap-env:Body/*'); - return $saml; + return ($subject, $saml); } =head2 handle_request( $request ) @@ -119,11 +128,16 @@ sub handle_request { my $saml = $parser->findnodes_as_string('/soap-env:Envelope/soap-env:Body/*'); if (defined $saml) { - my $sig_verify = XML::Sig->new({ x509 => 1, cert_text => $self->idp_cert }); - my $ret = $sig_verify->verify($saml); - return unless $ret; + my $x = XML::Sig->new({ x509 => 1, cert_text => $self->idp_cert }); + my $ret = $x->verify($saml); + die "bad signature" unless $ret; + + my $cert = $x->signer_cert; + my $ca = Crypt::OpenSSL::VerifyX509->new($self->cacert); + $ret = $ca->verify($cert); + die "bad certificate in request: ".$cert->subject unless $ret; - my $subject = $sig_verify->signer_cert->subject; + my $subject = $cert->subject; return ($subject, $saml); } diff --git a/lib/Net/SAML2/SP.pm b/lib/Net/SAML2/SP.pm index c98fd7b..124a372 100644 --- a/lib/Net/SAML2/SP.pm +++ b/lib/Net/SAML2/SP.pm @@ -207,6 +207,7 @@ sub soap_binding { cert => $self->cert, url => $idp_url, idp_cert => $idp_cert, + cacert => $self->cacert, ); return $soap;