@@ -89,60 +89,54 @@ EncryptedAssertion is properly validated.
8989sub new_from_xml {
9090 my ($class , %args ) = @_ ;
9191
92- my $dom = no_comments($args {xml });
9392 my $key_file = $args {key_file };
94- my $cacert = $args {cacert };
93+ my $cacert = delete $args {cacert };
9594
96- my $xpath = XML::LibXML::XPathContext-> new($dom );
95+ my $xpath = XML::LibXML::XPathContext-> new();
9796 $xpath -> registerNs(' saml' , ' urn:oasis:names:tc:SAML:2.0:assertion' );
9897 $xpath -> registerNs(' samlp' , ' urn:oasis:names:tc:SAML:2.0:protocol' );
99- $xpath -> registerNs(' xenc' , ' http://www.w3.org/2001/04/xmlenc#' );
98+ $xpath -> registerNs(' dsig' , ' http://www.w3.org/2000/09/xmldsig#' );
99+ $xpath -> registerNs(' xenc' , ' http://www.w3.org/2001/04/xmlenc#' );
100100
101- my $attributes = {};
101+ my $xml = no_comments($args {xml });
102+ $xpath -> setContextNode($xml );
102103
103- if ($xpath -> findnodes(' //saml:EncryptedAssertion' )) {
104- if ( ! defined $key_file ) {
105- die " Encrypted Assertions require key_file" ;
106- }
107- my $decrypted ;
108- my $enc = XML::Enc-> new(
109- { key => $key_file , no_xml_declaration => 1 }, );
110- $decrypted = $enc -> decrypt($dom -> toString());
111- $dom = XML::LibXML-> load_xml(string => $decrypted );
112- $xpath = XML::LibXML::XPathContext-> new($dom );
113- $xpath -> registerNs(' saml' , ' urn:oasis:names:tc:SAML:2.0:assertion' );
114- $xpath -> registerNs(' samlp' , ' urn:oasis:names:tc:SAML:2.0:protocol' );
115- $xpath -> registerNs(' dsig' , ' http://www.w3.org/2000/09/xmldsig#' );
116- $xpath -> registerNs(' xenc' , ' http://www.w3.org/2001/04/xmlenc#' );
117-
118- my $xml_opts -> { no_xml_declaration } = 1;
104+ my $dom = $xml ;
105+
106+ if ($xpath -> exists (' //saml:EncryptedAssertion' )) {
107+
108+ croak " Encrypted Assertions require key_file" if !defined $key_file ;
119109
120110 my $assert = $xpath -> findnodes(' //saml:Assertion' )-> [0];
121111 my @signedinfo = $xpath -> findnodes(' dsig:Signature' , $assert );
122112
123113 if (defined $assert && (scalar @signedinfo ne 0)) {
114+ my $xml_opts -> { no_xml_declaration } = 1;
124115 my $x = Net::SAML2::XML::Sig-> new($xml_opts );
125116 my $ret = $x -> verify($assert -> serialize);
126117 die " Decrypted Assertion signature check failed" unless $ret ;
127118
128- if ( $cacert ) {
129- my $cert = $x -> signer_cert
130- or die " Certificate not provided and not in SAML Response, cannot validate" ;
119+ return unless $cacert ;
120+ my $cert = $x -> signer_cert
121+ or die " Certificate not provided and not in SAML Response, cannot validate" ;
131122
132- my $ca = Crypt::OpenSSL::Verify-> new($cacert , { strict_certs => 0, });
133- if (! $ca -> verify($cert )) {
134- die " Decrypted Assertion - Unable to verify signer cert with cacert: $cert ->subject" ;
135- }
136- }
123+ my $ca = Crypt::OpenSSL::Verify-> new($cacert , { strict_certs => 0 });
124+ die " Unable to verify signer cert with cacert: " . $cert -> subject
125+ unless $ca -> verify($cert );
137126 }
138127 }
139128
140- for my $node (
141- $xpath -> findnodes(' //saml:Assertion/saml:AttributeStatement/saml:Attribute' ))
129+ my $dec = $class -> _decrypt(
130+ $xml ,
131+ key_file => $key_file ,
132+ key_name => $args {key_name }
133+ );
134+ $xpath -> setContextNode($dec );
135+
136+ my $attributes = {};
137+ for my $node ($xpath -> findnodes(' //saml:Assertion/saml:AttributeStatement/saml:Attribute/saml:AttributeValue/..' ))
142138 {
143- # We can't select by saml:AttributeValue
144- # because of https://rt.cpan.org/Public/Bug/Display.html?id=8784
145- my @values = $node -> findnodes(" *[local-name()='AttributeValue']" );
139+ my @values = $xpath -> findnodes(" saml:AttributeValue" , $node );
146140 $attributes -> {$node -> getAttribute(' Name' )} = [map $_ -> string_value, @values ];
147141 }
148142
@@ -171,7 +165,7 @@ sub new_from_xml {
171165 }
172166
173167 my $nameid ;
174- if (my $node = $xpath -> findnodes(' // samlp:Response/saml:Assertion/saml:Subject/ saml:NameID' )) {
168+ if (my $node = $xpath -> findnodes(' /samlp:Response/saml:Assertion/saml:Subject/saml:NameID' )) {
175169 $nameid = $node -> get_node(1);
176170 }
177171 elsif (my $global = $xpath -> findnodes(' //saml:Subject/saml:NameID' )) {
@@ -209,6 +203,7 @@ sub new_from_xml {
209203 return $self ;
210204}
211205
206+
212207=head2 response_status
213208
214209Returns the response status
@@ -335,4 +330,20 @@ sub success {
335330 return 0;
336331}
337332
333+ sub _decrypt {
334+ my $self = shift ;
335+ my $xml = shift ;
336+ my %options = @_ ;
337+
338+ return $xml unless $options {key_file };
339+
340+ my $enc = XML::Enc-> new(
341+ {
342+ no_xml_declaration => 1,
343+ key => $options {key_file },
344+ }
345+ );
346+ return XML::LibXML-> load_xml(string => $enc -> decrypt($xml , %options ));
347+ }
348+
3383491;
0 commit comments