ruby-saml-mod 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/onelogin/saml.rb CHANGED
@@ -4,6 +4,12 @@ require "rexml/document"
4
4
  require "xml_sec"
5
5
 
6
6
  module Onelogin
7
+ NAMESPACES = {
8
+ "samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
9
+ "saml" => "urn:oasis:names:tc:SAML:2.0:assertion",
10
+ "xenc" => "http://www.w3.org/2001/04/xmlenc#",
11
+ "ds" => "http://www.w3.org/2000/09/xmldsig#"
12
+ }
7
13
  end
8
14
 
9
15
  require 'onelogin/saml/auth_request'
@@ -1,17 +1,37 @@
1
1
  module Onelogin::Saml
2
2
  class MetaData
3
3
  def self.create(settings)
4
- %{<?xml version="1.0"?>
5
- <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="#{settings.issuer}">
6
- <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
7
- <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="#{settings.sp_slo_url}"/>
8
- <AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="#{settings.assertion_consumer_service_url}"/>
9
- </SPSSODescriptor>
10
- <ContactPerson contactType="technical">
11
- <SurName>#{settings.tech_contact_name}</SurName>
12
- <EmailAddress>mailto:#{settings.tech_contact_email}</EmailAddress>
13
- </ContactPerson>
14
- </EntityDescriptor>}
4
+ xml = %{<?xml version="1.0"?>
5
+ <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="#{settings.issuer}">
6
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
7
+ }
8
+ if settings.encryption_configured?
9
+ xml += %{
10
+ <KeyDescriptor use="encryption">
11
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
12
+ <X509Data>
13
+ <X509Certificate>
14
+ #{File.read(settings.xmlsec_certificate).gsub(/\w*-+(BEGIN|END) CERTIFICATE-+\w*/, "").strip}
15
+ </X509Certificate>
16
+ </X509Data>
17
+ </KeyInfo>
18
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
19
+ <KeySize xmlns="http://www.w3.org/2001/04/xmlenc#">128</KeySize>
20
+ </EncryptionMethod>
21
+ </KeyDescriptor>
22
+ }
23
+ end
24
+ xml += %{
25
+ <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="#{settings.sp_slo_url}"/>
26
+ <AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="#{settings.assertion_consumer_service_url}"/>
27
+ </SPSSODescriptor>
28
+ <ContactPerson contactType="technical">
29
+ <SurName>#{settings.tech_contact_name}</SurName>
30
+ <EmailAddress>mailto:#{settings.tech_contact_email}</EmailAddress>
31
+ </ContactPerson>
32
+ </EntityDescriptor>
33
+ }
34
+ xml
15
35
  end
16
36
  end
17
- end
37
+ end
@@ -1,23 +1,22 @@
1
1
  module Onelogin::Saml
2
2
  class Response
3
3
 
4
- attr_accessor :settings, :document, :response
4
+ attr_accessor :settings, :document, :xml, :response
5
5
  attr_accessor :name_id, :name_qualifier, :session_index
6
6
  attr_accessor :status_code, :status_message
7
- def initialize(response)
7
+ def initialize(response, settings)
8
8
  @response = response
9
- @document = XMLSecurity::SignedDocument.new(Base64.decode64(@response))
10
- @name_id = @document.elements["/samlp:Response/saml:Assertion/saml:Subject/saml:NameID"].text rescue nil
11
- @name_qualifier = @document.elements["/samlp:Response/saml:Assertion/saml:Subject/saml:NameID"].attributes["NameQualifier"] rescue nil
12
- @session_index = @document.elements["/samlp:Response/saml:Assertion/saml:AuthnStatement"].attributes["SessionIndex"] rescue nil
13
- @status_code = @document.elements["/samlp:Response/samlp:Status/samlp:StatusCode"].attributes["Value"] rescue nil
14
- @status_message = @document.elements["/samlp:Response/samlp:Status/samlp:StatusCode"].text rescue nil
15
- # look for saml2 and saml2p tags in Shibboleth assertions
16
- @name_id ||= @document.elements["/saml2p:Response/saml2:Assertion/saml2:Subject/saml2:NameID"].text rescue nil
17
- @name_qualifier ||= @document.elements["/saml2p:Response/saml2:Assertion/saml2:Subject/saml2:NameID"].attributes["NameQualifier"] rescue nil
18
- @session_index ||= @document.elements["/saml2p:Response/saml2:Assertion/saml2:AuthnStatement"].attributes["SessionIndex"] rescue nil
19
- @status_code ||= @document.elements["/saml2p:Response/saml2p:Status/saml2p:StatusCode"].attributes["Value"] rescue nil
20
- @status_message ||= @document.elements["/saml2p:Response/saml2p:Status/saml2p:StatusCode"].text rescue nil
9
+ @settings = settings
10
+
11
+ @xml = Base64.decode64(@response)
12
+ @document = XMLSecurity::SignedDocument.new(@xml)
13
+ @document.decrypt(@settings)
14
+
15
+ @name_id = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).text rescue nil
16
+ @name_qualifier = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).attributes["NameQualifier"] rescue nil
17
+ @session_index = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:AuthnStatement", Onelogin::NAMESPACES).attributes["SessionIndex"] rescue nil
18
+ @status_code = REXML::XPath.first(@document, "/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).attributes["Value"] rescue nil
19
+ @status_message = REXML::XPath.first(@document, "/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).text rescue nil
21
20
  end
22
21
 
23
22
  def logger=(val)
@@ -41,5 +41,20 @@ module Onelogin::Saml
41
41
 
42
42
  # The email of the technical contact for your application
43
43
  attr_accessor :tech_contact_email
44
+
45
+ ## Attributes for xml encryption
46
+
47
+ # The path to the xmlsec1 binary used for xml decryption
48
+ attr_accessor :xmlsec1_path
49
+
50
+ # The PEM-encoded certificate
51
+ attr_accessor :xmlsec_certificate
52
+
53
+ # The PEM-encoded private key
54
+ attr_accessor :xmlsec_privatekey
55
+
56
+ def encryption_configured?
57
+ self.xmlsec1_path && self.xmlsec_certificate && self.xmlsec_privatekey
58
+ end
44
59
  end
45
60
  end
data/lib/xml_sec.rb CHANGED
@@ -28,6 +28,8 @@ require "rexml/xpath"
28
28
  require "openssl"
29
29
  require "xmlcanonicalizer"
30
30
  require "digest/sha1"
31
+ require "tempfile"
32
+ require "shellwords"
31
33
 
32
34
  module XMLSecurity
33
35
 
@@ -86,6 +88,28 @@ module XMLSecurity
86
88
 
87
89
  return valid_flag
88
90
  end
89
-
91
+
92
+ def decrypt(settings)
93
+ if settings.encryption_configured?
94
+ REXML::XPath.each(self, "//xenc:EncryptedData", Onelogin::NAMESPACES) do |node|
95
+ Tempfile.open("ruby-saml-decrypt") do |f|
96
+ f.puts node.to_s
97
+ f.close
98
+ command = [ settings.xmlsec1_path, "decrypt", "--privkey-pem", settings.xmlsec_privatekey, f.path ].shelljoin
99
+ decrypted_xml = %x{#{command}}
100
+ if $?.exitstatus != 0
101
+ @logger.warn "Could not decrypt: #{decrypted_xml}" if @logger
102
+ return false
103
+ else
104
+ decrypted_doc = REXML::Document.new(decrypted_xml)
105
+ decrypted_node = decrypted_doc.root
106
+ node.parent.replace_with(decrypted_node)
107
+ end
108
+ f.unlink
109
+ end
110
+ end
111
+ end
112
+ true
113
+ end
90
114
  end
91
115
  end
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{ruby-saml-mod}
3
- s.version = "0.1.2"
3
+ s.version = "0.1.4"
4
4
 
5
- s.authors = ["OneLogin LLC", "Bracken"]
6
- s.date = %q{2011-01-26}
5
+ s.authors = ["OneLogin LLC", "Bracken", "Zach"]
6
+ s.date = %q{2011-11-05}
7
7
  s.extra_rdoc_files = [
8
8
  "LICENSE"
9
9
  ]
metadata CHANGED
@@ -1,22 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml-mod
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 1
9
- - 2
10
- version: 0.1.2
8
+ - 4
9
+ version: 0.1.4
11
10
  platform: ruby
12
11
  authors:
13
12
  - OneLogin LLC
14
13
  - Bracken
14
+ - Zach
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-01-26 00:00:00 -07:00
19
+ date: 2011-11-05 00:00:00 -06:00
20
20
  default_executable:
21
21
  dependencies: []
22
22
 
@@ -51,27 +51,23 @@ rdoc_options: []
51
51
  require_paths:
52
52
  - lib
53
53
  required_ruby_version: !ruby/object:Gem::Requirement
54
- none: false
55
54
  requirements:
56
55
  - - ">="
57
56
  - !ruby/object:Gem::Version
58
- hash: 3
59
57
  segments:
60
58
  - 0
61
59
  version: "0"
62
60
  required_rubygems_version: !ruby/object:Gem::Requirement
63
- none: false
64
61
  requirements:
65
62
  - - ">="
66
63
  - !ruby/object:Gem::Version
67
- hash: 3
68
64
  segments:
69
65
  - 0
70
66
  version: "0"
71
67
  requirements: []
72
68
 
73
69
  rubyforge_project:
74
- rubygems_version: 1.6.2
70
+ rubygems_version: 1.3.6
75
71
  signing_key:
76
72
  specification_version: 3
77
73
  summary: Ruby library for SAML service providers