saml2 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b77541aa53787757d03865855dbbb84da27edaba
4
- data.tar.gz: f53032507b4c09f95e1e0f2def917e8760a5f41a
3
+ metadata.gz: 102b176691a071893741f0bf750836e0bc72e8f0
4
+ data.tar.gz: afac3ee0941535c504f75c7b24137f55a1021f27
5
5
  SHA512:
6
- metadata.gz: 2658dc70caec44d8a6b2d8b3e014f419a2887a82a43dc6e2280c1f43437d5d162bc86b9197f144d386709317f4f39b1d692d8bb03d0bd340943fd460ec8d430f
7
- data.tar.gz: 5fcd948501794284e79ba05f8296c4d5e9492f4624210b80fafde2edd760f47de26476bed1f67b8f6e8607c682e5f6e732b40a796ba03a47503c324c8d037cfc
6
+ metadata.gz: 2a982caa3e5e5ac9ad4a392f8b6a680f85e330b0a3ed898a2b9dccf2896f4a282a1aba14e5743466aaac7f4b368ff8b40e75ccb03ef2e89b35c658c9a90b1a16
7
+ data.tar.gz: 251540ba69cc06316961865d9333b5d4da0a8ebcb3c9622039483c87ce222f9e221280087bcfedc36669c77f6539a27716f228fb0218083c6a590c0b7ed51b75
@@ -24,7 +24,7 @@ module SAML2
24
24
 
25
25
  def from_xml(node)
26
26
  # pass through for subclasses
27
- super unless self == Attribute
27
+ return super unless self == Attribute
28
28
 
29
29
  # look for an appropriate subclass
30
30
  klass = class_for(node)
@@ -76,7 +76,6 @@ module SAML2
76
76
  when 1; values.first
77
77
  else; values
78
78
  end
79
- super
80
79
  end
81
80
 
82
81
  private
@@ -128,8 +127,6 @@ module SAML2
128
127
  @attributes = node.xpath('saml:Attribute', Namespaces::ALL).map do |attr|
129
128
  Attribute.from_xml(attr)
130
129
  end
131
-
132
- super
133
130
  end
134
131
 
135
132
  def build(builder)
@@ -12,8 +12,8 @@ module SAML2
12
12
  end
13
13
 
14
14
  def from_xml(node)
15
- @is_required = node['isRequired'] && node['isRequired'] == 'true'
16
15
  super
16
+ @is_required = node['isRequired'] && node['isRequired'] == 'true'
17
17
  end
18
18
 
19
19
  def required?
@@ -47,13 +47,13 @@ module SAML2
47
47
  attr_reader :name, :requested_attributes
48
48
 
49
49
  def initialize(name = nil, requested_attributes = [])
50
+ super()
50
51
  @name, @requested_attributes = name, requested_attributes
51
52
  end
52
53
 
53
54
  def from_xml(node)
54
55
  @name = node['ServiceName']
55
56
  @requested_attributes = load_object_array(node, "md:RequestedAttribute", RequestedAttribute)
56
- super
57
57
  end
58
58
 
59
59
  def create_statement(attributes)
@@ -4,11 +4,12 @@ module SAML2
4
4
  class Base
5
5
  def self.from_xml(node)
6
6
  return nil unless node
7
- new.from_xml(node)
7
+ result = new
8
+ result.from_xml(node)
9
+ result
8
10
  end
9
11
 
10
- def from_xml(node)
11
- self
12
+ def from_xml(_node)
12
13
  end
13
14
 
14
15
  def to_s
@@ -17,7 +18,7 @@ module SAML2
17
18
  end
18
19
 
19
20
  def to_xml
20
- unless @document
21
+ unless instance_variable_defined?(:@document)
21
22
  builder = Nokogiri::XML::Builder.new
22
23
  build(builder)
23
24
  @document = builder.doc
@@ -11,7 +11,7 @@ module SAML2
11
11
 
12
12
  attr_reader :location, :binding
13
13
 
14
- def initialize(location, binding = Bindings::HTTP_POST)
14
+ def initialize(location = nil, binding = Bindings::HTTP_POST)
15
15
  @location, @binding = location, binding
16
16
  end
17
17
 
@@ -22,7 +22,6 @@ module SAML2
22
22
  def from_xml(node)
23
23
  @location = node['Location']
24
24
  @binding = node['Binding']
25
- self
26
25
  end
27
26
 
28
27
  def build(builder, element)
@@ -28,44 +28,91 @@ module SAML2
28
28
 
29
29
  class Group < Array
30
30
  def self.from_xml(node)
31
- node && new(node)
31
+ node && new.from_xml(node)
32
32
  end
33
33
 
34
- def initialize(root)
35
- @root = root
34
+ def initialize
35
+ @valid_until = nil
36
+ end
37
+
38
+ def from_xml(node)
39
+ @root = node
40
+ remove_instance_variable(:@valid_until)
36
41
  replace(Base.load_object_array(@root, "md:EntityDescriptor|md:EntitiesDescriptor",
37
42
  'EntityDescriptor' => Entity,
38
43
  'EntitiesDescriptor' => Group))
39
44
  end
40
45
 
41
46
  def valid_schema?
42
- Schemas.metadata.valid?(@root.document)
47
+ Schemas.federation.valid?(@root.document)
48
+ end
49
+
50
+ def signature
51
+ unless instance_variable_defined?(:@signature)
52
+ @signature = @root.at_xpath('dsig:Signature', Namespaces::ALL)
53
+ signed_node = @signature.at_xpath('dsig:SignedInfo/dsig:Reference', Namespaces::ALL)['URI']
54
+ @root.set_id_attribute('ID')
55
+ @signature = nil unless signed_node == "##{@root['ID']}"
56
+ end
57
+ @signature
58
+ end
59
+
60
+ def signed?
61
+ !!signature
62
+ end
63
+
64
+ def valid_signature?(*args)
65
+ signature.verify_with(*args)
66
+ end
67
+
68
+ def valid_until
69
+ unless instance_variable_defined?(:@valid_until)
70
+ @valid_until = @root['validUntil'] && Time.parse(@root['validUntil'])
71
+ end
72
+ @valid_until
43
73
  end
44
74
  end
45
75
 
46
- def self.from_xml(node)
47
- node && new(node)
76
+ def initialize
77
+ super
78
+ @valid_until = nil
79
+ @entity_id = nil
80
+ @roles = []
48
81
  end
49
82
 
50
- def initialize(root = nil)
83
+ def from_xml(node)
84
+ @root = node
85
+ remove_instance_variable(:@valid_until)
86
+ @roles = nil
51
87
  super
52
- @root = root
53
- unless @root
54
- @roles = []
55
- end
56
88
  end
57
89
 
58
90
  def valid_schema?
59
- Schemas.metadata.valid?(@root.document)
91
+ Schemas.federation.valid?(@root.document)
60
92
  end
61
93
 
62
94
  def entity_id
63
95
  @entity_id || @root && @root['entityID']
64
96
  end
65
97
 
98
+ def valid_until
99
+ unless instance_variable_defined?(:@valid_until)
100
+ @valid_until = @root['validUntil'] && Time.parse(@root['validUntil'])
101
+ end
102
+ @valid_until
103
+ end
104
+
105
+ def identity_providers
106
+ roles.select { |r| r.is_a?(IdentityProvider) }
107
+ end
108
+
109
+ def service_providers
110
+ roles.select { |r| r.is_a?(ServiceProvider) }
111
+ end
112
+
66
113
  def roles
67
- # TODO: load IdPSSODescriptors as well
68
- @roles ||= load_object_array(@root, 'md:SPSSODescriptor', ServiceProvider)
114
+ @roles ||= load_object_array(@root, 'md:IDPSSODescriptor', IdentityProvider) +
115
+ load_object_array(@root, 'md:SPSSODescriptor', ServiceProvider)
69
116
  end
70
117
 
71
118
  def build(builder)
@@ -5,14 +5,20 @@ module SAML2
5
5
  class IdentityProvider < SSO
6
6
  attr_writer :want_authn_requests_signed, :single_sign_on_services, :attribute_profiles, :attributes
7
7
 
8
- def initialize(node = nil)
9
- super(node)
10
- unless node
11
- @want_authn_requests_signed = nil
12
- @single_sign_on_services = []
13
- @attribute_profiles = []
14
- @attributes = []
15
- end
8
+ def initialize
9
+ super
10
+ @want_authn_requests_signed = nil
11
+ @single_sign_on_services = []
12
+ @attribute_profiles = []
13
+ @attributes = []
14
+ end
15
+
16
+ def from_xml(node)
17
+ super
18
+ remove_instance_variable(:@want_authn_requests_signed)
19
+ @single_sign_on_services = nil
20
+ @attribute_profiles = nil
21
+ @attributes = nil
16
22
  end
17
23
 
18
24
  def want_authn_requests_signed?
@@ -4,6 +4,11 @@ module SAML2
4
4
  module IndexedObject
5
5
  attr_reader :index
6
6
 
7
+ def initialize(*args)
8
+ @is_default = nil
9
+ super
10
+ end
11
+
7
12
  def eql?(rhs)
8
13
  index == rhs.index &&
9
14
  default? == rhs.default? &&
@@ -11,7 +16,7 @@ module SAML2
11
16
  end
12
17
 
13
18
  def default?
14
- @is_default
19
+ !!@is_default
15
20
  end
16
21
 
17
22
  def from_xml(node)
@@ -29,6 +29,14 @@ module SAML2
29
29
  use.nil? || use == Type::SIGNING
30
30
  end
31
31
 
32
+ def certificate
33
+ @certificate ||= OpenSSL::X509::Certificate.new(Base64.decode64(x509))
34
+ end
35
+
36
+ def fingerprint
37
+ @fingerprint ||= Digest::SHA1.hexdigest(certificate.to_der).gsub(/(\h{2})(?=\h)/, '\1:')
38
+ end
39
+
32
40
  def build(builder)
33
41
  builder['md'].KeyDescriptor do |builder|
34
42
  builder.parent['use'] = use if use
@@ -5,11 +5,15 @@ module SAML2
5
5
  module OrganizationAndContacts
6
6
  attr_writer :organization, :contacts
7
7
 
8
- def initialize(node = nil)
9
- unless node
10
- @organization = nil
11
- @contacts = []
12
- end
8
+ def initialize
9
+ @organization = nil
10
+ @contacts = []
11
+ end
12
+
13
+ def from_xml(node)
14
+ remove_instance_variable(:@organization)
15
+ @contacts = nil
16
+ super
13
17
  end
14
18
 
15
19
  def organization
@@ -14,14 +14,18 @@ module SAML2
14
14
 
15
15
  attr_writer :supported_protocols, :keys
16
16
 
17
- def initialize(node = nil)
17
+ def initialize
18
+ super
19
+ @supported_protocols = Set.new
20
+ @supported_protocols << Protocols::SAML2
21
+ @keys = []
22
+ end
23
+
24
+ def from_xml(node)
18
25
  super
19
26
  @root = node
20
- unless @root
21
- @supported_protocols = Set.new
22
- @supported_protocols << Protocols::SAML2
23
- @keys = []
24
- end
27
+ @supported_protocols = nil
28
+ @keys = nil
25
29
  end
26
30
 
27
31
  def supported_protocols
@@ -1,5 +1,9 @@
1
1
  module SAML2
2
2
  module Schemas
3
+ def self.federation
4
+ @federation ||= schema('ws-federation.xsd')
5
+ end
6
+
3
7
  def self.metadata
4
8
  @metadata ||= schema('saml-schema-metadata-2.0.xsd')
5
9
  end
@@ -5,14 +5,6 @@ require 'saml2/sso'
5
5
 
6
6
  module SAML2
7
7
  class ServiceProvider < SSO
8
- class << self
9
- alias_method :from_xml, :new
10
- end
11
-
12
- def initialize(root)
13
- @root = root
14
- end
15
-
16
8
  def assertion_consumer_services
17
9
  @assertion_consumer_services ||= begin
18
10
  nodes = @root.xpath('md:AssertionConsumerService', Namespaces::ALL)
@@ -4,12 +4,16 @@ module SAML2
4
4
  class SSO < Role
5
5
  attr_reader :single_logout_services, :name_id_formats
6
6
 
7
- def initialize(node = nil)
7
+ def initialize
8
8
  super
9
- unless node
10
- @single_logout_services = []
11
- @name_id_formats = []
12
- end
9
+ @single_logout_services = []
10
+ @name_id_formats = []
11
+ end
12
+
13
+ def from_xml(node)
14
+ super
15
+ @single_logout_services = nil
16
+ @name_id_formats = nil
13
17
  end
14
18
 
15
19
  def single_logout_services
@@ -1,3 +1,3 @@
1
1
  module SAML2
2
- VERSION = '1.0.5'
2
+ VERSION = '1.0.6'
3
3
  end
@@ -0,0 +1,112 @@
1
+ <?xml version='1.0' encoding='UTF-8' ?>
2
+ <!--
3
+ (c) 2004-2006 BEA Systems Inc., Computer Associates International, Inc.,
4
+ International Business Machines Corporation, Microsoft Corporation,
5
+ Inc., SAP AG, Sun Microsystems, and webMethods. All rights reserved.
6
+
7
+ Permission to copy and display the WS-MetadataExchange Specification
8
+ (the "Specification"), in any medium without fee or royalty is hereby
9
+ granted, provided that you include the following on ALL copies of the
10
+ Specification that you make:
11
+
12
+ 1. A link or URL to the Specification at this location.
13
+ 2. The copyright notice as shown in the Specification.
14
+
15
+ BEA Systems, Computer Associates, IBM, Microsoft, SAP, Sun, and
16
+ webMethods (collectively, the "Authors") each agree to grant you a
17
+ license, under royalty-free and otherwise reasonable,
18
+ non-discriminatory terms and conditions, to their respective essential
19
+ patent claims that they deem necessary to implement the
20
+ WS-MetadataExchange Specification.
21
+
22
+ THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
23
+ REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
24
+ LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25
+ PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE
26
+ SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
27
+ IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY
28
+ PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
29
+
30
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
31
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
32
+ USE OR DISTRIBUTION OF THE SPECIFICATIONS.
33
+
34
+ The name and trademarks of the Authors may NOT be used in any manner,
35
+ including advertising or publicity pertaining to the Specifications or
36
+ their contents without specific, written prior permission. Title to
37
+ copyright in the Specifications will at all times remain with the
38
+ Authors.
39
+
40
+ No other rights are granted by implication, estoppel or otherwise.
41
+ -->
42
+
43
+ <xs:schema
44
+ targetNamespace='http://schemas.xmlsoap.org/ws/2004/09/mex'
45
+ xmlns:tns='http://schemas.xmlsoap.org/ws/2004/09/mex'
46
+ xmlns:wsa10='http://www.w3.org/2005/08/addressing'
47
+ xmlns:wsa04='http://schemas.xmlsoap.org/ws/2004/08/addressing'
48
+ xmlns:xs='http://www.w3.org/2001/XMLSchema'
49
+ elementFormDefault='qualified'
50
+ blockDefault='#all' >
51
+
52
+ <!-- Get Metadata request -->
53
+ <xs:element name='GetMetadata' >
54
+ <xs:complexType>
55
+ <xs:sequence>
56
+ <xs:element ref='tns:Dialect' minOccurs='0' />
57
+ <xs:element ref='tns:Identifier' minOccurs='0' />
58
+ </xs:sequence>
59
+ <xs:anyAttribute namespace='##other' processContents='lax' />
60
+ </xs:complexType>
61
+ </xs:element>
62
+
63
+ <xs:element name='Dialect' type='xs:anyURI' />
64
+ <xs:element name='Identifier' type='xs:anyURI' />
65
+
66
+ <!-- Get Metadata response -->
67
+ <xs:element name='Metadata' >
68
+ <xs:complexType>
69
+ <xs:sequence>
70
+ <xs:element ref='tns:MetadataSection'
71
+ minOccurs='0'
72
+ maxOccurs='unbounded' />
73
+ <xs:any namespace='##other' processContents='lax'
74
+ minOccurs='0'
75
+ maxOccurs='unbounded' />
76
+ </xs:sequence>
77
+ <xs:anyAttribute namespace='##other' processContents='lax' />
78
+ </xs:complexType>
79
+ </xs:element>
80
+
81
+ <xs:element name='MetadataSection' >
82
+ <xs:complexType>
83
+ <xs:choice>
84
+ <xs:any namespace='##other' processContents='lax' />
85
+ <xs:element ref='tns:MetadataReference' />
86
+ <xs:element ref='tns:Location' />
87
+ </xs:choice>
88
+ <xs:attribute name='Dialect' type='xs:anyURI' use='required' />
89
+ <xs:attribute name='Identifier' type='xs:anyURI' />
90
+ <xs:anyAttribute namespace='##other' processContents='lax' />
91
+ </xs:complexType>
92
+ </xs:element>
93
+
94
+ <!--
95
+ Ideally, the type of the MetadataReference would have been
96
+ the union of wsa04:EndpointReferenceType and
97
+ wsa10:EndpointReferenceType but unfortunately xs:union only
98
+ works for simple types. As a result, we have to define
99
+ the mex:MetadataReference using xs:any.
100
+ -->
101
+
102
+ <xs:element name='MetadataReference'>
103
+ <xs:complexType>
104
+ <xs:sequence>
105
+ <xs:any minOccurs='1' maxOccurs='unbounded'
106
+ processContents='lax' namespace='##other' />
107
+ </xs:sequence>
108
+ </xs:complexType>
109
+ </xs:element>
110
+ <xs:element name='Location'
111
+ type='xs:anyURI' />
112
+ </xs:schema>