Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Net/SAML2/Binding/POST.pm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ sub handle_response {

# unpack and check the signature
my $xml = decode_base64($response);
my $x = Net::SAML2::XML::Sig->new({ x509 => 1 });
my $x = Net::SAML2::XML::Sig->new({ x509 => 1, cert => $self->cacert });
my $ret = $x->verify($xml);
die "signature check failed" unless $ret;

Expand Down
13 changes: 8 additions & 5 deletions lib/Net/SAML2/Binding/Redirect.pm
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,16 @@ sub verify {
my $u = URI->new($url);

# verify the response
my $sigalg = $u->query_param('SigAlg');
die "can't verify '$sigalg' signatures"
unless $sigalg eq 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';

my $cert = Crypt::OpenSSL::X509->new_from_string($self->cert);
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($cert->pubkey);


my $sigalg = $u->query_param('SigAlg');
if ($sigalg eq 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256') {
$rsa_pub->use_sha256_hash();
} else {
die "can't verify '$sigalg' signatures"
unless $sigalg eq 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
}
my $sig = decode_base64($u->query_param_delete('Signature'));
my $signed = $u->query;
die "bad sig" unless $rsa_pub->verify($signed, $sig);
Expand Down
8 changes: 4 additions & 4 deletions lib/Net/SAML2/IdP.pm
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Constructor
has 'entityid' => (isa => Str, is => 'ro', required => 1);
has 'cacert' => (isa => Str, is => 'ro', required => 1);
has 'sso_urls' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'slo_urls' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'art_urls' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'slo_urls' => (isa => HashRef[Str], is => 'ro');
has 'art_urls' => (isa => HashRef[Str], is => 'ro');
has 'certs' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'formats' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'default_format' => (isa => Str, is => 'ro', required => 1);
Expand Down Expand Up @@ -123,8 +123,8 @@ sub new_from_xml {
my $self = $class->new(
entityid => $xpath->findvalue('//md:EntityDescriptor/@entityID')->value,
sso_urls => $data->{SSO},
slo_urls => $data->{SLO},
art_urls => $data->{Art},
(defined $data->{SLO} ? (slo_urls => $data->{SLO}) : () ),
(defined $data->{Art} ? (art_urls => $data->{Art}) : () ),
certs => $data->{Cert},
formats => $data->{NameIDFormat},
default_format => $data->{DefaultFormat},
Expand Down
2 changes: 1 addition & 1 deletion lib/Net/SAML2/Role/ProtocolMessage.pm
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ around 'BUILDARGS' => sub {
my %args = @_;

# random ID for this message
$args{id} ||= unpack 'H*', Crypt::OpenSSL::Random::random_pseudo_bytes(16);
$args{id} ||='_' . unpack 'H*', Crypt::OpenSSL::Random::random_pseudo_bytes(16);

# IssueInstant in UTC
my $dt = DateTime->now( time_zone => 'UTC' );
Expand Down
35 changes: 23 additions & 12 deletions lib/Net/SAML2/XML/Sig.pm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use base qw/Exporter/;

use strict;

use Digest::SHA1 qw(sha1 sha1_base64);
use Digest::SHA qw(sha1 sha256);
use XML::XPath;
use MIME::Base64;
use Carp;
Expand Down Expand Up @@ -136,9 +136,24 @@ sub verify {
my $signed_info = XML::XPath::XMLParser::as_string($signed_info_node);
my $signed_info_canon = $self->_canonicalize_xml( $signed_info );

my $sigalg = $self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:SignatureMethod/@Algorithm');
my $digest_method = $self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestMethod/@Algorithm');
my $digest = _trim($self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestValue'));

my $signed_xml = $self->_get_signed_xml();
my $canonical = $self->_transform($signed_xml, $signature_node);
my $digest_bin;
if ($digest_method eq 'http://www.w3.org/2000/09/xmldsig#sha1') {
$digest_bin = sha1($canonical);
} elsif ($digest_method eq 'http://www.w3.org/2001/04/xmlenc#sha256') {
$digest_bin = sha256($canonical);
}

return 0 unless ($digest eq _trim(encode_base64($digest_bin)));

if (defined $self->{cert_obj}) {
# use the provided cert to verify
return 0 unless $self->_verify_x509_cert($self->{cert_obj},$signed_info_canon,$signature);
return 0 unless $self->_verify_x509_cert($self->{cert_obj},$signed_info_canon,$signature,$sigalg);
}
else {
# extract the certficate or key from the document
Expand All @@ -157,15 +172,7 @@ sub verify {
}
}

my $digest_method = $self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestMethod/@Algorithm');
my $digest = _trim($self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestValue'));

my $signed_xml = $self->_get_signed_xml();
my $canonical = $self->_transform($signed_xml, $signature_node);
my $digest_bin = sha1($canonical);

return 1 if ($digest eq _trim(encode_base64($digest_bin)));
return 0;
return 1;
}

sub signer_cert {
Expand Down Expand Up @@ -288,13 +295,17 @@ sub _verify_x509 {

sub _verify_x509_cert {
my $self = shift;
my ($cert, $canonical, $sig) = @_;
my ($cert, $canonical, $sig, $sigalg) = @_;

eval {
require Crypt::OpenSSL::RSA;
};
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($cert->pubkey);

if ($sigalg eq 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256') {
$rsa_pub->use_sha256_hash();
}

# Decode signature and verify
my $bin_signature = decode_base64($sig);

Expand Down