@@ -66,7 +66,7 @@ has 'cacert' => (isa => 'Maybe[Str]', is => 'ro', required => 1);
6666has ' sso_urls' => (isa => ' HashRef[Str]' , is => ' ro' , required => 1);
6767has ' slo_urls' => (isa => ' Maybe[HashRef[Str]]' , is => ' ro' );
6868has ' art_urls' => (isa => ' Maybe[HashRef[Str]]' , is => ' ro' );
69- has ' certs' => (isa => ' HashRef[Str]' , is => ' ro' , required => 1);
69+ has ' certs' => (isa => ' HashRef[ArrayRef[ Str]] ' , is => ' ro' , required => 1);
7070has ' sls_force_lcase_url_encoding' => (isa => ' Bool' , is => ' ro' , required => 0);
7171has ' sls_double_encoded_response' => (isa => ' Bool' , is => ' ro' , required => 0);
7272
@@ -180,10 +180,15 @@ sub new_from_xml {
180180 }
181181 }
182182
183+ my @certs = ();
184+
183185 for my $key (
184186 $xpath -> findnodes(' //md:EntityDescriptor/md:IDPSSODescriptor/md:KeyDescriptor' ))
185187 {
186- my $use = $key -> getAttribute(' use' ) || ' signing' ;
188+ my @uses ;
189+ push (@uses , $key -> getAttribute(' use' ) || ' signing' );
190+ push (@uses , ' encryption' ) if !$key -> getAttribute(' use' );
191+
187192
188193 $key -> setNamespace(' http://www.w3.org/2000/09/xmldsig#' , ' ds' );
189194
@@ -204,17 +209,20 @@ sub new_from_xml {
204209 $text = join " \n " , @lines ;
205210
206211 # form a PEM certificate
207- $data -> {Cert }-> {$use }
208- = sprintf (" -----BEGIN CERTIFICATE-----\n %s \n -----END CERTIFICATE-----\n " ,
209- $text );
212+ for my $use (@uses ) {
213+ my $pem -> {$use }
214+ = sprintf (" -----BEGIN CERTIFICATE-----\n %s \n -----END CERTIFICATE-----\n " ,
215+ $text );
216+ push (@certs , $pem );
217+ }
210218 }
211219
212220 my $self = $class -> new(
213221 entityid => $xpath -> findvalue(' //md:EntityDescriptor/@entityID' ),
214222 sso_urls => $data -> {SSO },
215223 slo_urls => $data -> {SLO } || {},
216224 art_urls => $data -> {Art } || {},
217- certs => $data -> { Cert } ,
225+ certs => \ @certs ,
218226 cacert => $args {cacert },
219227 sls_force_lcase_url_encoding => $args {sls_force_lcase_url_encoding },
220228 sls_double_encoded_response => $args {sls_double_encoded_response },
@@ -229,28 +237,50 @@ sub new_from_xml {
229237 return $self ;
230238}
231239
232- =head2 BUILD ( hashref of the parameters passed to the constructor )
233-
234- Called after the object is created to validate the IdP using the cacert
235-
236- =cut
237-
238- sub BUILD {
239- my ($self ) = @_ ;
240+ # BUILDARGS ( hashref of the parameters passed to the constructor )
241+ #
242+ # Called after the object is created to validate the IdP using the cacert
243+ #
244+
245+ around BUILDARGS => sub {
246+ my $orig = shift ;
247+ my $self = shift ;
248+
249+ my %params = @_ ;
250+
251+ if ($params {cacert }) {
252+ my $ca = Crypt::OpenSSL::Verify-> new($params {cacert }, { strict_certs => 0, });
253+
254+ my $verified = 0;
255+ my %errors ;
256+ my %certs ;
257+
258+ for my $pem (@{ $params {certs } }) {
259+ for my $use (keys %{$pem }) {
260+ my @tmpcrt ;
261+ my $cert = Crypt::OpenSSL::X509-> new_from_string($pem -> {$use });
262+ # # BUGBUG this is failing for valid things ...
263+ eval { $ca -> verify($cert ) };
264+ if ($@ ) {
265+ $errors {$cert -> fingerprint_sha256} = $@ ;
266+ next ;
267+ }
268+ $verified = 1;
269+ push @tmpcrt , $pem -> {$use };
270+
271+ $certs {$use } = \@tmpcrt ;
272+ }
273+ }
240274
241- if ($self -> cacert) {
242- my $ca = Crypt::OpenSSL::Verify-> new($self -> cacert, { strict_certs => 0, });
275+ $params {certs } = \%certs ;
243276
244- for my $use (keys %{$self -> certs}) {
245- my $cert = Crypt::OpenSSL::X509-> new_from_string($self -> certs-> {$use });
246- # # BUGBUG this is failing for valid things ...
247- eval { $ca -> verify($cert ) };
248- if ($@ ) {
249- warn " Can't verify IdP '$use ' cert: $@ \n " ;
250- }
277+ if (!$verified ) {
278+ warn " Can't verify IdP signing cert: " , %errors , " \n " ;
251279 }
252280 }
253- }
281+
282+ return $self -> $orig (%params );
283+ };
254284
255285=head2 sso_url( $binding )
256286
@@ -290,7 +320,13 @@ sub art_url {
290320
291321=head2 cert( $use )
292322
293- Returns the IdP's certificate for the given use (e.g. C<signing > ).
323+ Returns the IdP's certificates for the given use (e.g. C<signing > ).
324+
325+ IdP's are generated from the metadata it is possible for multiple certificates
326+ to be contained in the metadata and therefore possible for them to be there to
327+ be multiple verified certs in $self->certs. At this point any certs in the IdP
328+ have been verified and are valid for the specified use. All certs are of type
329+ $use are returned.
294330
295331=cut
296332
@@ -310,6 +346,7 @@ sub binding {
310346 my ($self , $name ) = @_ ;
311347
312348 my $bindings = {
349+ post => ' urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' ,
313350 redirect => ' urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect' ,
314351 soap => ' urn:oasis:names:tc:SAML:2.0:bindings:SOAP' ,
315352 };
0 commit comments