ruby-saml-mod 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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