ruby-saml-mod 0.2.5 → 0.2.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e32a73407cbd1dc9486c6dbce36be93fc18ee2d
4
- data.tar.gz: c2cce4b017515e1e0878cf29b12ffc6d4608c3a9
3
+ metadata.gz: c9717bd6a9dffb64cf2ae4f45ff7f386059af316
4
+ data.tar.gz: 363c5cedd4ec2a9705129c559547e5fd0336ebf9
5
5
  SHA512:
6
- metadata.gz: fdc92ccf552bce1ab44d5a59c6582cf5023653314cf192d70847eefd14fae74f36eea0f95f12de5949ae2e508ba5f2659c1d95f6e66fb6b5d6ea0297b9218442
7
- data.tar.gz: 7650aabfd1abba4969558447d7308faa456e51f7d77009ff042376df9d7b3e6a50d0a0e955a90ea207c3150ab4bc4128d6cfb3bc7893aeebe1047933bf1fed4b
6
+ metadata.gz: 466ef19f37dcddd3f17fa608e1fe6981cec73228463adc876fd610ff7b637a9c7cbb9301910e0c44e9153c20dc126baed7ab0007f72ee287bdcb57090864cbdd
7
+ data.tar.gz: fa770d00d673b9c5a5fd42a1492b9260049554c3c146c941f86ed881a63f5bca351f8786560ad06bf31e5f9478914a208905ec531f5e2b8f9311f78adc608e97
data/lib/onelogin/saml.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'zlib'
2
2
  require "base64"
3
- require "xml/libxml"
3
+ require "nokogiri"
4
4
  require "xml_sec"
5
5
  require "cgi"
6
6
 
@@ -29,7 +29,7 @@ module Onelogin::Saml
29
29
  end
30
30
 
31
31
  def document
32
- @document ||= LibXML::XML::Document.string(xml) if xml
32
+ @document ||= Nokogiri::XML(xml) if xml
33
33
  end
34
34
 
35
35
  def xml=(value)
@@ -117,11 +117,11 @@ module Onelogin::Saml
117
117
  end
118
118
 
119
119
  def node_attribute_value(xpath, attribute)
120
- document.root.find_first(xpath, Onelogin::NAMESPACES)[attribute] rescue nil
120
+ document.root.at_xpath(xpath, Onelogin::NAMESPACES)[attribute] rescue nil
121
121
  end
122
122
 
123
123
  def node_content(xpath)
124
- document.root.find_first(xpath, Onelogin::NAMESPACES).content rescue nil
124
+ document.root.at_xpath(xpath, Onelogin::NAMESPACES).content rescue nil
125
125
  end
126
126
 
127
127
  def self.generate_unique_id(length = 42)
@@ -13,7 +13,7 @@ module Onelogin::Saml
13
13
 
14
14
  begin
15
15
  @xml = Base64.decode64(@response)
16
- @document = LibXML::XML::Document.string(@xml)
16
+ @document = Nokogiri::XML(@xml)
17
17
  @document.extend(XMLSecurity::SignedDocument)
18
18
  rescue
19
19
  # could not parse document, everything is invalid
@@ -21,9 +21,9 @@ module Onelogin::Saml
21
21
  return
22
22
  end
23
23
 
24
- @issuer = document.find_first("/samlp:Response/saml:Issuer", Onelogin::NAMESPACES).content.strip rescue nil
25
- @issuer ||= document.find_first("/samlp:Response/saml:Assertion/saml:Issuer", Onelogin::NAMESPACES).content.strip rescue nil
26
- @status_code = document.find_first("/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES)["Value"] rescue nil
24
+ @issuer = document.at_xpath("/samlp:Response/saml:Issuer", Onelogin::NAMESPACES).content.strip rescue nil
25
+ @issuer ||= document.at_xpath("/samlp:Response/saml:Assertion/saml:Issuer", Onelogin::NAMESPACES).content.strip rescue nil
26
+ @status_code = document.at_xpath("/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES)["Value"] rescue nil
27
27
 
28
28
  process(settings) if settings
29
29
  end
@@ -55,14 +55,15 @@ module Onelogin::Saml
55
55
  end
56
56
 
57
57
  def decrypted_document
58
- @decrypted_document ||= LibXML::XML::Document.document(document).tap do |doc|
59
- doc.extend(XMLSecurity::SignedDocument)
60
- doc.decrypt!(settings)
58
+ unless @decrypted_document
59
+ document.decrypt!(settings)
60
+ @decrypted_document = document
61
61
  end
62
+ @decrypted_document
62
63
  end
63
64
 
64
65
  def untrusted_find_first(xpath)
65
- decrypted_document.find(xpath, Onelogin::NAMESPACES).first
66
+ decrypted_document.at_xpath(xpath, Onelogin::NAMESPACES)
66
67
  end
67
68
 
68
69
  def trusted_find_first(xpath)
@@ -71,7 +72,7 @@ module Onelogin::Saml
71
72
 
72
73
  def trusted_find(xpath)
73
74
  trusted_roots.map do |trusted_root|
74
- trusted_root.find("descendant-or-self::#{xpath}", Onelogin::NAMESPACES).to_a
75
+ trusted_root.xpath("descendant-or-self::#{xpath}", Onelogin::NAMESPACES).to_a
75
76
  end.flatten.compact
76
77
  end
77
78
 
@@ -141,7 +142,7 @@ module Onelogin::Saml
141
142
  end
142
143
 
143
144
  def fingerprint_from_idp
144
- if base64_cert = decrypted_document.find_first("//ds:X509Certificate", Onelogin::NAMESPACES)
145
+ if base64_cert = decrypted_document.at_xpath("//ds:X509Certificate", Onelogin::NAMESPACES)
145
146
  cert_text = Base64.decode64(base64_cert.content)
146
147
  cert = OpenSSL::X509::Certificate.new(cert_text)
147
148
  Digest::SHA1.hexdigest(cert.to_der)
data/lib/xml_sec.rb CHANGED
@@ -25,7 +25,7 @@
25
25
  require 'rubygems'
26
26
  require 'ffi'
27
27
  require 'base64'
28
- require "xml/libxml"
28
+ require "nokogiri"
29
29
  require "openssl"
30
30
  require "digest/sha1"
31
31
 
@@ -330,7 +330,7 @@ module XMLSecurity
330
330
 
331
331
  def signed_roots
332
332
  signatures.map do |sig|
333
- ref = sig.find('./ds:SignedInfo/ds:Reference', Onelogin::NAMESPACES).first
333
+ ref = sig.at_xpath('./ds:SignedInfo/ds:Reference', Onelogin::NAMESPACES)
334
334
  signed_element_id = ref['URI'].sub(/^#/, '')
335
335
 
336
336
  if signed_element_id.empty?
@@ -338,19 +338,19 @@ module XMLSecurity
338
338
  else
339
339
  xpath_id_query = %Q(ancestor::*[@ID = "#{signed_element_id}"])
340
340
 
341
- ref.find(xpath_id_query, Onelogin::NAMESPACES).first
341
+ ref.at_xpath(xpath_id_query, Onelogin::NAMESPACES)
342
342
  end
343
343
  end.compact
344
344
  end
345
345
 
346
346
  def signatures
347
347
  # we only return the first, cause our signature validation only checks the first
348
- @signatures ||= [self.find_first("//ds:Signature", Onelogin::NAMESPACES)]
348
+ @signatures ||= [self.at_xpath("//ds:Signature", Onelogin::NAMESPACES)].compact
349
349
  end
350
350
 
351
351
  def validate(idp_cert_fingerprint, logger = nil)
352
352
  # get cert from response
353
- base64_cert = self.find_first("//ds:X509Certificate", Onelogin::NAMESPACES).content
353
+ base64_cert = self.at_xpath("//ds:X509Certificate", Onelogin::NAMESPACES).content
354
354
  cert_text = Base64.decode64(base64_cert)
355
355
  cert = OpenSSL::X509::Certificate.new(cert_text)
356
356
 
@@ -364,21 +364,8 @@ module XMLSecurity
364
364
  end
365
365
  end
366
366
 
367
- # create a copy of the document with the certificate removed
368
- doc = LibXML::XML::Document.new
369
- # doc.encoding = self.encoding == XML::Encoding::NONE ? XML::Encoding::ISO_8859_1 : self.encoding
370
-
371
- # for some reason xmlsec doesn't like it when its UTF-8 and has other
372
- # characters with umlauts and the like. We will just force it to another encoding.
373
- # This should work fine since we are just validating the signature.
374
- doc.encoding = XML::Encoding::ISO_8859_1
375
-
376
- doc.root = doc.import(self.root)
377
- sigcert = doc.find_first("//ds:Signature/ds:KeyInfo", Onelogin::NAMESPACES)
378
- sigcert.remove!
379
-
380
367
  # Force encoding of the xml and the xml string for validation
381
- xml = doc.to_s(:indent => false, :encoding => doc.encoding).encode(doc.rb_encoding)
368
+ xml = to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: "ISO-8859-1")
382
369
 
383
370
  # validate it!
384
371
  validate_doc(xml, SignedDocument.format_cert(cert))
@@ -432,14 +419,13 @@ module XMLSecurity
432
419
  # replaces EncryptedData nodes with decrypted copies
433
420
  def decrypt!(settings)
434
421
  if settings.encryption_configured?
435
- find("//xenc:EncryptedData", Onelogin::NAMESPACES).each do |node|
422
+ xpath("//xenc:EncryptedData", Onelogin::NAMESPACES).each do |node|
436
423
  decrypted_xml = decrypt_node(settings, node.to_s)
437
424
  if decrypted_xml
438
- decrypted_doc = LibXML::XML::Document.string(decrypted_xml)
425
+ decrypted_doc = Nokogiri::XML(decrypted_xml)
439
426
  decrypted_node = decrypted_doc.root
440
- decrypted_node = self.import(decrypted_node)
441
427
  node.parent.next = decrypted_node
442
- node.parent.remove!
428
+ node.parent.unlink
443
429
  end
444
430
  end
445
431
  end
@@ -43,18 +43,18 @@ describe Onelogin::Saml::LogoutRequest do
43
43
  let(:forward_url) { logout_request.forward_url }
44
44
 
45
45
  it "includes destination in the saml:LogoutRequest attributes" do
46
- logout_xml = LibXML::XML::Document.string(logout_request.xml)
47
- logout_xml.find_first('/samlp:LogoutRequest', Onelogin::NAMESPACES).attributes['Destination'].should == "http://idp.example.com/saml2"
46
+ logout_xml = Nokogiri::XML(logout_request.xml)
47
+ logout_xml.at_xpath('/samlp:LogoutRequest', Onelogin::NAMESPACES)['Destination'].should == "http://idp.example.com/saml2"
48
48
  end
49
49
 
50
50
  it "properly sets the Format attribute NameID based on settings" do
51
- logout_xml = LibXML::XML::Document.string(logout_request.xml)
52
- logout_xml.find_first('/samlp:LogoutRequest/saml:NameID', Onelogin::NAMESPACES).attributes['Format'].should == Onelogin::Saml::NameIdentifiers::UNSPECIFIED
51
+ logout_xml = Nokogiri::XML(logout_request.xml)
52
+ logout_xml.at_xpath('/samlp:LogoutRequest/saml:NameID', Onelogin::NAMESPACES)['Format'].should == Onelogin::Saml::NameIdentifiers::UNSPECIFIED
53
53
  end
54
54
 
55
55
  it "does not include the signature in the request xml" do
56
- logout_xml = LibXML::XML::Document.string(logout_request.xml)
57
- logout_xml.find_first('/samlp:LogoutRequest/ds:Signature', Onelogin::NAMESPACES).should be_nil
56
+ logout_xml = Nokogiri::XML(logout_request.xml)
57
+ logout_xml.at_xpath('/samlp:LogoutRequest/ds:Signature', Onelogin::NAMESPACES).should be_nil
58
58
  end
59
59
 
60
60
  it "can sign the generated query string" do
@@ -25,37 +25,37 @@ describe Onelogin::Saml::LogoutResponse do
25
25
  end
26
26
 
27
27
  it "includes destination in the saml:LogoutRequest attributes" do
28
- value = xml.find_first('/samlp:LogoutResponse', Onelogin::NAMESPACES).attributes['Destination']
28
+ value = xml.at_xpath('/samlp:LogoutResponse', Onelogin::NAMESPACES)['Destination']
29
29
  expect(value).to eq "http://idp.example.com/saml2?existing=param&existing=param"
30
30
  end
31
31
 
32
32
  it "includes id in the saml:LogoutRequest attributes" do
33
- value = xml.find_first('/samlp:LogoutResponse', Onelogin::NAMESPACES).attributes['ID']
33
+ value = xml.at_xpath('/samlp:LogoutResponse', Onelogin::NAMESPACES)['ID']
34
34
  expect(value).to eq id
35
35
  end
36
36
 
37
37
  it "includes issue_instant in the saml:LogoutRequest attributes" do
38
- value = xml.find_first('/samlp:LogoutResponse', Onelogin::NAMESPACES).attributes['IssueInstant']
38
+ value = xml.at_xpath('/samlp:LogoutResponse', Onelogin::NAMESPACES)['IssueInstant']
39
39
  expect(value).to eq issue_instant
40
40
  end
41
41
 
42
42
  it "includes in_response_to in the saml:LogoutRequest attributes" do
43
- value = xml.find_first('/samlp:LogoutResponse', Onelogin::NAMESPACES).attributes['InResponseTo']
43
+ value = xml.at_xpath('/samlp:LogoutResponse', Onelogin::NAMESPACES)['InResponseTo']
44
44
  expect(value).to eq in_response_to
45
45
  end
46
46
 
47
47
  it "includes issuer tag" do
48
- value = xml.find_first("/samlp:LogoutResponse/saml:Issuer", Onelogin::NAMESPACES).content
48
+ value = xml.at_xpath("/samlp:LogoutResponse/saml:Issuer", Onelogin::NAMESPACES).content
49
49
  expect(value).to eq issuer
50
50
  end
51
51
 
52
52
  it "includes status code tag" do
53
- value = xml.find_first("/samlp:LogoutResponse/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).attributes['Value']
53
+ value = xml.at_xpath("/samlp:LogoutResponse/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES)['Value']
54
54
  expect(value).to eq Onelogin::Saml::StatusCodes::SUCCESS_URI
55
55
  end
56
56
 
57
57
  it "includes status message tag" do
58
- value = xml.find_first("/samlp:LogoutResponse/samlp:Status/samlp:StatusMessage", Onelogin::NAMESPACES).content
58
+ value = xml.at_xpath("/samlp:LogoutResponse/samlp:Status/samlp:StatusMessage", Onelogin::NAMESPACES).content
59
59
  expect(value).to eq Onelogin::Saml::LogoutResponse::STATUS_MESSAGE
60
60
  end
61
61
 
@@ -32,7 +32,7 @@ describe Onelogin::Saml::MetaData do
32
32
  )
33
33
  doc = REXML::Document.new Onelogin::Saml::MetaData.create(settings)
34
34
  key_descriptors = REXML::XPath.match(doc, "//KeyDescriptor")
35
- key_descriptors.should have(2).keys
35
+ key_descriptors.length.should == 2
36
36
  key_descriptors[0].attributes["use"].should == "encryption"
37
37
  key_descriptors[1].attributes["use"].should == "signing"
38
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml-mod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - OneLogin LLC
@@ -14,22 +14,22 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2015-07-17 00:00:00.000000000 Z
17
+ date: 2015-08-03 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
- name: libxml-ruby
20
+ name: nokogiri
21
21
  requirement: !ruby/object:Gem::Requirement
22
22
  requirements:
23
- - - ">="
23
+ - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 2.3.0
25
+ version: '1.6'
26
26
  type: :runtime
27
27
  prerelease: false
28
28
  version_requirements: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 2.3.0
32
+ version: '1.6'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: ffi
35
35
  requirement: !ruby/object:Gem::Requirement