libsaml 2.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +91 -0
- data/Rakefile +33 -0
- data/lib/saml.rb +142 -0
- data/lib/saml/artifact.rb +51 -0
- data/lib/saml/artifact_resolve.rb +10 -0
- data/lib/saml/artifact_response.rb +9 -0
- data/lib/saml/assertion.rb +67 -0
- data/lib/saml/authn_request.rb +34 -0
- data/lib/saml/base.rb +47 -0
- data/lib/saml/bindings/http_artifact.rb +44 -0
- data/lib/saml/bindings/http_post.rb +29 -0
- data/lib/saml/bindings/http_redirect.rb +100 -0
- data/lib/saml/bindings/soap.rb +31 -0
- data/lib/saml/complex_types/endpoint_type.rb +17 -0
- data/lib/saml/complex_types/indexed_endpoint_type.rb +15 -0
- data/lib/saml/complex_types/request_abstract_type.rb +57 -0
- data/lib/saml/complex_types/sso_descriptor_type.rb +48 -0
- data/lib/saml/complex_types/status_response_type.rb +29 -0
- data/lib/saml/config.rb +49 -0
- data/lib/saml/elements/attribute.rb +24 -0
- data/lib/saml/elements/attribute_statement.rb +26 -0
- data/lib/saml/elements/audience_restriction.rb +12 -0
- data/lib/saml/elements/authn_context.rb +13 -0
- data/lib/saml/elements/authn_statement.rb +25 -0
- data/lib/saml/elements/conditions.rb +24 -0
- data/lib/saml/elements/contact_person.rb +33 -0
- data/lib/saml/elements/entities_descriptor.rb +27 -0
- data/lib/saml/elements/entity_descriptor.rb +37 -0
- data/lib/saml/elements/idp_sso_descriptor.rb +23 -0
- data/lib/saml/elements/key_descriptor.rb +34 -0
- data/lib/saml/elements/key_descriptor/key_info.rb +30 -0
- data/lib/saml/elements/key_descriptor/key_info/x509_data.rb +34 -0
- data/lib/saml/elements/name_id.rb +14 -0
- data/lib/saml/elements/organization.rb +16 -0
- data/lib/saml/elements/requested_authn_context.rb +28 -0
- data/lib/saml/elements/signature.rb +33 -0
- data/lib/saml/elements/signature/canonicalization_method.rb +19 -0
- data/lib/saml/elements/signature/digest_method.rb +19 -0
- data/lib/saml/elements/signature/inclusive_namespaces.rb +20 -0
- data/lib/saml/elements/signature/key_info.rb +14 -0
- data/lib/saml/elements/signature/reference.rb +23 -0
- data/lib/saml/elements/signature/signature_method.rb +19 -0
- data/lib/saml/elements/signature/signed_info.rb +24 -0
- data/lib/saml/elements/signature/transform.rb +19 -0
- data/lib/saml/elements/signature/transforms.rb +21 -0
- data/lib/saml/elements/sp_sso_descriptor.rb +27 -0
- data/lib/saml/elements/status.rb +15 -0
- data/lib/saml/elements/status_code.rb +42 -0
- data/lib/saml/elements/sub_status_code.rb +14 -0
- data/lib/saml/elements/subject.rb +38 -0
- data/lib/saml/elements/subject_confirmation.rb +30 -0
- data/lib/saml/elements/subject_confirmation_data.rb +23 -0
- data/lib/saml/elements/subject_locality.rb +12 -0
- data/lib/saml/encoding.rb +35 -0
- data/lib/saml/logout_request.rb +10 -0
- data/lib/saml/logout_response.rb +11 -0
- data/lib/saml/provider.rb +85 -0
- data/lib/saml/provider_stores/file.rb +33 -0
- data/lib/saml/response.rb +21 -0
- data/lib/saml/util.rb +51 -0
- data/lib/saml/version.rb +3 -0
- data/lib/saml/xml_helpers.rb +34 -0
- data/lib/tasks/saml_tasks.rake +4 -0
- metadata +195 -0
data/lib/saml/config.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Saml
|
2
|
+
module Config
|
3
|
+
mattr_accessor :provider_type
|
4
|
+
@@provider_type = "service_provider"
|
5
|
+
|
6
|
+
mattr_accessor :provider_store
|
7
|
+
@@provider_store = Saml::ProviderStores::File.new
|
8
|
+
|
9
|
+
mattr_accessor :entity_id
|
10
|
+
@@entity_id = 'SamlEntity'
|
11
|
+
|
12
|
+
mattr_accessor :authn_context_levels
|
13
|
+
@@authn_context_levels = {}
|
14
|
+
|
15
|
+
mattr_accessor :artifact_ttl
|
16
|
+
@@artifact_ttl = 15
|
17
|
+
|
18
|
+
mattr_accessor :private_key
|
19
|
+
@@private_key = 'PRIVATE_KEY'
|
20
|
+
|
21
|
+
mattr_accessor :private_key_file
|
22
|
+
@@private_key_file = 'PRIVATE_KEY_FILE'
|
23
|
+
|
24
|
+
mattr_accessor :max_issue_instant_offset
|
25
|
+
@@max_issue_instant_offset = 2
|
26
|
+
|
27
|
+
mattr_accessor :absolute_timeout
|
28
|
+
@@absolute_timeout = 8*60
|
29
|
+
|
30
|
+
mattr_accessor :graceperiod_timeout
|
31
|
+
@@graceperiod_timeout = 15
|
32
|
+
|
33
|
+
mattr_accessor :session_timeout
|
34
|
+
@@session_timeout = 15
|
35
|
+
|
36
|
+
# SSL
|
37
|
+
mattr_accessor :ssl_private_key
|
38
|
+
@@ssl_private_key = 'SSL_PRIVATE_KEY'
|
39
|
+
|
40
|
+
mattr_accessor :ssl_private_key_file
|
41
|
+
@@ssl_private_key_file = 'SSL_PRIVATE_KEY_FILE'
|
42
|
+
|
43
|
+
mattr_accessor :ssl_certificate
|
44
|
+
@@ssl_certificate = 'SSL_CERTIFICATE'
|
45
|
+
|
46
|
+
mattr_accessor :ssl_certificate_file
|
47
|
+
@@ssl_certificate_file = 'SSL_CERTIFICATE_FILE'
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class Attribute
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag "Attribute"
|
7
|
+
register_namespace 'saml', Saml::SAML_NAMESPACE
|
8
|
+
namespace 'saml'
|
9
|
+
|
10
|
+
attribute :name, String, :tag => 'Name'
|
11
|
+
attribute :format, String, tag: 'NameFormat'
|
12
|
+
attribute :friendly_name, String, tag: 'FriendlyName'
|
13
|
+
element :attribute_value, String, :namespace => 'saml', :tag => "AttributeValue"
|
14
|
+
|
15
|
+
validates :name, :presence => true
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
options = args.extract_options!
|
19
|
+
super(*(args << options))
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class AttributeStatement
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag "AttributeStatement"
|
7
|
+
register_namespace 'saml', Saml::SAML_NAMESPACE
|
8
|
+
namespace 'saml'
|
9
|
+
|
10
|
+
has_many :attribute, Saml::Elements::Attribute
|
11
|
+
|
12
|
+
def initialize(*args)
|
13
|
+
options = args.extract_options!
|
14
|
+
super(*(args << options))
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch_attribute(key)
|
18
|
+
attribute = self.attribute.find do |attr|
|
19
|
+
attr.name == key
|
20
|
+
end
|
21
|
+
attribute.attribute_value if attribute
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class AuthnContext
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag "AuthnContext"
|
7
|
+
namespace 'saml'
|
8
|
+
element :authn_context_class_ref, String, :tag => "AuthnContextClassRef"
|
9
|
+
|
10
|
+
validates :authn_context_class_ref, :inclusion => ClassRefs::ALL_CLASS_REFS + [nil]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class AuthnStatement
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag "AuthnStatement"
|
7
|
+
namespace 'saml'
|
8
|
+
|
9
|
+
attribute :authn_instant, Time, :tag => "AuthnInstant", :on_save => lambda { |val| val.utc.xmlschema }
|
10
|
+
attribute :session_index, String, :tag => "SessionIndex"
|
11
|
+
|
12
|
+
has_one :subject_locality, Saml::Elements::SubjectLocality, :tag => "SubjectLocality"
|
13
|
+
has_one :authn_context, Saml::Elements::AuthnContext, :tag => "AuthnContext"
|
14
|
+
|
15
|
+
validates :authn_instant, :authn_context, :presence => true
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
options = args.extract_options!
|
19
|
+
@subject_locality = Saml::Elements::SubjectLocality.new(:address => options.delete(:address)) if options[:address]
|
20
|
+
@authn_context = Saml::Elements::AuthnContext.new(:authn_context_class_ref => options.delete(:authn_context_class_ref)) if options[:authn_context_class_ref]
|
21
|
+
super(*(args << options))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class Conditions
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag "Conditions"
|
7
|
+
namespace 'saml'
|
8
|
+
|
9
|
+
attribute :not_before, Time, :tag => "NotBefore", :on_save => lambda { |val| val.utc.xmlschema }
|
10
|
+
attribute :not_on_or_after, Time, :tag => "NotOnOrAfter", :on_save => lambda { |val| val.utc.xmlschema }
|
11
|
+
|
12
|
+
has_one :audience_restriction, Saml::Elements::AudienceRestriction
|
13
|
+
|
14
|
+
def initialize(*args)
|
15
|
+
options = args.extract_options!
|
16
|
+
@audience_restriction = Saml::Elements::AudienceRestriction.new(:audience => options.delete(:audience)) if options[:audience]
|
17
|
+
self.not_before = Time.now - Saml::Config.max_issue_instant_offset.minutes
|
18
|
+
self.not_on_or_after = Time.now + Saml::Config.max_issue_instant_offset.minutes
|
19
|
+
super(*(args << options))
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class ContactPerson
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag 'ContactPerson'
|
7
|
+
namespace 'md'
|
8
|
+
|
9
|
+
module ContactTypes
|
10
|
+
TECHNICAL = 'technical'
|
11
|
+
SUPPORT = 'support'
|
12
|
+
ADMINISTRATIVE = 'administrative'
|
13
|
+
BILLING = 'billing'
|
14
|
+
OTHER = 'other'
|
15
|
+
|
16
|
+
ALL = [TECHNICAL, SUPPORT, ADMINISTRATIVE, BILLING, OTHER]
|
17
|
+
end
|
18
|
+
|
19
|
+
attribute :contact_type, String, :tag => "ContactType"
|
20
|
+
|
21
|
+
element :company, String, :tag => "Company"
|
22
|
+
element :given_name, String, :tag => "GivenName"
|
23
|
+
element :sur_name, String, :tag => "SurName"
|
24
|
+
|
25
|
+
has_many :email_addresses, String, :tag => "EmailAddress"
|
26
|
+
has_many :telephone_numbers, String, :tag => "TelephoneNumber"
|
27
|
+
|
28
|
+
validates :contact_type, :inclusion => ContactTypes::ALL
|
29
|
+
|
30
|
+
validates :email_addresses, :telephone_numbers, :presence => true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class EntitiesDescriptor
|
4
|
+
include Saml::Base
|
5
|
+
include Saml::XMLHelpers
|
6
|
+
|
7
|
+
register_namespace "md", Saml::MD_NAMESPACE
|
8
|
+
|
9
|
+
tag "EntitiesDescriptor"
|
10
|
+
namespace "md"
|
11
|
+
|
12
|
+
attribute :_id, String, :tag => "ID"
|
13
|
+
attribute :name, String, :tag => "Name"
|
14
|
+
attribute :valid_until, Time, :tag => "validUntil"
|
15
|
+
attribute :cache_duration, Integer, :tag => "cacheDuration"
|
16
|
+
|
17
|
+
has_one :signature, Saml::Elements::Signature
|
18
|
+
|
19
|
+
has_many :entities_descriptors, Saml::Elements::EntitiesDescriptor
|
20
|
+
has_many :entity_descriptors, Saml::Elements::EntityDescriptor
|
21
|
+
|
22
|
+
validates :entities_descriptors, :length => { :minimum => 1 }, :if => lambda { |ed| ed.entity_descriptors.blank? }
|
23
|
+
validates :entity_descriptors, :length => { :minimum => 1 }, :if => lambda { |ed| ed.entities_descriptors.blank? }
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class EntityDescriptor
|
4
|
+
include Saml::Base
|
5
|
+
include Saml::XMLHelpers
|
6
|
+
|
7
|
+
|
8
|
+
register_namespace 'md', Saml::MD_NAMESPACE
|
9
|
+
|
10
|
+
tag 'EntityDescriptor'
|
11
|
+
namespace 'md'
|
12
|
+
|
13
|
+
attribute :_id, String, :tag => 'ID'
|
14
|
+
attribute :name, String, :tag => "Name"
|
15
|
+
attribute :entity_id, String, :tag => "entityID"
|
16
|
+
attribute :valid_until, Time, :tag => "validUntil"
|
17
|
+
attribute :cache_duration, Integer, :tag => "cacheDuration"
|
18
|
+
|
19
|
+
has_one :signature, Saml::Elements::Signature
|
20
|
+
|
21
|
+
has_one :organization, Saml::Elements::Organization
|
22
|
+
has_many :contact_persons, Saml::Elements::ContactPerson
|
23
|
+
|
24
|
+
has_one :idp_sso_descriptor, Saml::Elements::IDPSSODescriptor
|
25
|
+
has_one :sp_sso_descriptor, Saml::Elements::SPSSODescriptor
|
26
|
+
|
27
|
+
validates :entity_id, :presence => true
|
28
|
+
|
29
|
+
def initialize(*args)
|
30
|
+
super(*args)
|
31
|
+
@contact_persons ||= []
|
32
|
+
@_id ||= Saml.generate_id
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class IDPSSODescriptor
|
4
|
+
include Saml::ComplexTypes::SSODescriptorType
|
5
|
+
|
6
|
+
class SingleSignOnService
|
7
|
+
include Saml::ComplexTypes::EndpointType
|
8
|
+
tag 'SingleSignOnService'
|
9
|
+
end
|
10
|
+
|
11
|
+
tag 'IDPSSODescriptor'
|
12
|
+
|
13
|
+
has_many :single_sign_on_services, SingleSignOnService
|
14
|
+
|
15
|
+
validates :single_sign_on_services, :presence => true
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
super(*args)
|
19
|
+
self.single_sign_on_services ||= []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'saml/elements/key_descriptor/key_info'
|
2
|
+
|
3
|
+
module Saml
|
4
|
+
module Elements
|
5
|
+
class KeyDescriptor
|
6
|
+
include Saml::Base
|
7
|
+
|
8
|
+
module UseTypes
|
9
|
+
SIGNING = "signing"
|
10
|
+
ENCRYPTION = "encryption"
|
11
|
+
ALL = [SIGNING, ENCRYPTION, nil]
|
12
|
+
end
|
13
|
+
|
14
|
+
tag 'KeyDescriptor'
|
15
|
+
namespace 'md'
|
16
|
+
|
17
|
+
attribute :use, String, :tag => "use"
|
18
|
+
|
19
|
+
has_one :key_info, KeyInfo
|
20
|
+
|
21
|
+
validates :use, :inclusion => UseTypes::ALL
|
22
|
+
validates :certificate, :presence => true
|
23
|
+
|
24
|
+
def certificate
|
25
|
+
key_info.try(:x509Data).try(:x509certificate)
|
26
|
+
end
|
27
|
+
|
28
|
+
def certificate=(cert)
|
29
|
+
self.key_info = KeyInfo.new(cert)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'saml/elements/key_descriptor/key_info/x509_data'
|
2
|
+
|
3
|
+
module Saml
|
4
|
+
module Elements
|
5
|
+
class KeyDescriptor
|
6
|
+
class KeyInfo
|
7
|
+
include Saml::Base
|
8
|
+
|
9
|
+
register_namespace 'ds', Saml::XML_DSIG_NAMESPACE
|
10
|
+
namespace 'ds'
|
11
|
+
tag 'KeyInfo'
|
12
|
+
|
13
|
+
element :key_name, String, :namespace => 'ds', :tag => "KeyName"
|
14
|
+
|
15
|
+
has_one :x509Data, X509Data
|
16
|
+
|
17
|
+
validates :x509Data, :presence => true
|
18
|
+
|
19
|
+
def initialize(cert = nil)
|
20
|
+
if cert
|
21
|
+
self.x509Data = X509Data.new(cert)
|
22
|
+
end
|
23
|
+
if self.x509Data && self.x509Data.x509certificate
|
24
|
+
self.key_name = Digest::SHA1.hexdigest(self.x509Data.x509certificate.to_der)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class KeyDescriptor
|
4
|
+
class KeyInfo
|
5
|
+
class X509Data
|
6
|
+
include Saml::Base
|
7
|
+
|
8
|
+
tag 'X509Data'
|
9
|
+
namespace 'ds'
|
10
|
+
|
11
|
+
element :x509certificate, String, :tag => "X509Certificate", :on_save => lambda { |c| c.present? ? Base64.encode64(c.to_der) : "" }
|
12
|
+
|
13
|
+
validates :x509certificate, :presence => true
|
14
|
+
|
15
|
+
def initialize(cert = nil)
|
16
|
+
self.x509certificate = cert
|
17
|
+
end
|
18
|
+
|
19
|
+
def x509certificate=(cert)
|
20
|
+
if cert.present?
|
21
|
+
unless cert =~ /-----BEGIN CERTIFICATE-----/
|
22
|
+
cert = cert.gsub(/\n/, '')
|
23
|
+
cert = "-----BEGIN CERTIFICATE-----\n#{cert.gsub(/(.{1,64})/, "\\1\n")}-----END CERTIFICATE-----"
|
24
|
+
end
|
25
|
+
@x509certificate = OpenSSL::X509::Certificate.new(cert)
|
26
|
+
end
|
27
|
+
rescue OpenSSL::X509::CertificateError => e
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Saml
|
2
|
+
module Elements
|
3
|
+
class Organization
|
4
|
+
include Saml::Base
|
5
|
+
|
6
|
+
tag 'Organization'
|
7
|
+
namespace 'md'
|
8
|
+
|
9
|
+
has_many :organization_names, String, :tag => "OrganizationName"
|
10
|
+
has_many :organization_display_names, String, :tag => "OrganizationDisplayName"
|
11
|
+
has_many :organization_urls, String, :tag => "OrganizationURL"
|
12
|
+
|
13
|
+
validates :organization_names, :organization_display_names, :organization_urls, :presence => true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|