ruby-saml-mod 0.1.21 → 0.1.22

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.
@@ -16,14 +16,16 @@ module Onelogin::Saml
16
16
  @id = Onelogin::Saml::AuthRequest.generate_unique_id(42)
17
17
  issue_instant = Onelogin::Saml::AuthRequest.get_timestamp
18
18
 
19
- @request_xml = "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{@id}\" Version=\"2.0\" IssueInstant=\"#{issue_instant}\" Destination=\"#{@settings.idp_slo_target_url}\">" +
20
- "<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{@settings.issuer}</saml:Issuer>" +
21
- "<saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" NameQualifier=\"#{@session[:name_qualifier]}\" SPNameQualifier=\"#{@settings.issuer}\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">#{@session[:name_id]}</saml:NameID>" +
22
- "<samlp:SessionIndex xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">#{@session[:session_index]}</samlp:SessionIndex>" +
23
- "</samlp:LogoutRequest>"
19
+ @request_xml = <<-REQUEST_XML
20
+ <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="#{@id}" Version="2.0" IssueInstant="#{issue_instant}" Destination="#{@settings.idp_slo_target_url}">
21
+ <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">#{@settings.issuer}</saml:Issuer>
22
+ <saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" NameQualifier="#{@session[:name_qualifier]}" SPNameQualifier="#{@settings.issuer}" Format="#{@settings.name_identifier_format}">#{@session[:name_id]}</saml:NameID>
23
+ <samlp:SessionIndex xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">#{@session[:session_index]}</samlp:SessionIndex>
24
+ </samlp:LogoutRequest>
25
+ REQUEST_XML
24
26
 
25
27
  if settings.sign?
26
- @request_xml = XMLSecurity.sign(@request_xml, @settings.xmlsec_privatekey)
28
+ @request_xml = XMLSecurity.sign(@id, @request_xml, @settings.xmlsec_privatekey, @settings.xmlsec_certificate)
27
29
  end
28
30
 
29
31
  deflated_logout_request = Zlib::Deflate.deflate(@request_xml, 9)[2..-5]
data/lib/xml_sec.rb CHANGED
@@ -184,6 +184,7 @@ module XMLSecurity
184
184
  attach_function :xmlSecKeysMngrCreate, [], :pointer
185
185
  attach_function :xmlSecOpenSSLAppDefaultKeysMngrInit, [ :pointer ], :int
186
186
  attach_function :xmlSecOpenSSLAppKeyLoad, [ :string, :xmlSecKeyDataFormat, :pointer, :pointer, :pointer ], :pointer
187
+ attach_function :xmlSecOpenSSLAppKeyCertLoad, [ :pointer, :string, :xmlSecKeyDataFormat], :int
187
188
  attach_function :xmlSecOpenSSLAppKeyLoadMemory, [ :pointer, :uint, :xmlSecKeyDataFormat, :pointer, :pointer, :pointer ], :pointer
188
189
  attach_function :xmlSecOpenSSLAppDefaultKeysMngrAdoptKey, [ :pointer, :pointer ], :int
189
190
  attach_function :xmlSecKeysMngrDestroy, [ :pointer ], :void
@@ -207,6 +208,7 @@ module XMLSecurity
207
208
  attach_function :xmlSecKeySetName, [ :pointer, :string ], :int
208
209
 
209
210
  attach_function :xmlSecTmplKeyInfoAddKeyName, [ :pointer, :pointer ], :pointer
211
+ attach_function :xmlSecTmplKeyInfoAddX509Data, [ :pointer ], :pointer
210
212
 
211
213
  attach_function :xmlSecDSigCtxSign, [ :pointer, :pointer ], :int
212
214
 
@@ -308,11 +310,7 @@ module XMLSecurity
308
310
  doc = XMLSecurity.xmlSecParseMemory(xml, xml.length, 0)
309
311
  root = XMLSecurity.xmlDocGetRootElement(doc)
310
312
 
311
- # add the ID attribute as an id. yeah, hacky
312
- idary = FFI::MemoryPointer.new(:pointer, 2)
313
- idary[0].put_pointer(0, FFI::MemoryPointer.from_string("ID"))
314
- idary[1].put_pointer(0, nil)
315
- XMLSecurity.xmlSecAddIDs(doc, root, idary)
313
+ XMLSecurity.register_xml_id_attribute(doc, root)
316
314
 
317
315
  # get the root node, and then find the signature
318
316
  node = XMLSecurity.xmlSecFindNode(root, "Signature", "http://www.w3.org/2000/09/xmldsig#")
@@ -402,7 +400,7 @@ module XMLSecurity
402
400
 
403
401
  class SignatureFailure < RuntimeError; end
404
402
 
405
- def self.sign(xml_string, private_key)
403
+ def self.sign(reference_id, xml_string, private_key, certificate)
406
404
  doc = self.xmlParseMemory(xml_string, xml_string.size)
407
405
  raise SignatureFailure.new("could not parse XML document") if doc.null?
408
406
 
@@ -412,9 +410,12 @@ module XMLSecurity
412
410
  sign_node = self.xmlSecTmplSignatureCreate(doc, canonicalization_method_id, sign_method_id, nil)
413
411
 
414
412
  raise SignatureFailure.new("failed to create signature template") if sign_node.null?
415
- self.xmlAddChild(self.xmlDocGetRootElement(doc), sign_node)
413
+ root = self.xmlDocGetRootElement(doc)
414
+ self.xmlAddChild(root, sign_node)
416
415
 
417
- ref_node = self.xmlSecTmplSignatureAddReference(sign_node, self.xmlSecOpenSSLTransformSha1GetKlass, nil, nil, nil)
416
+ XMLSecurity.register_xml_id_attribute(doc, root)
417
+
418
+ ref_node = self.xmlSecTmplSignatureAddReference(sign_node, self.xmlSecOpenSSLTransformSha1GetKlass, nil, reference_id && "##{reference_id}", nil)
418
419
  raise SignatureFailure.new("failed to add a reference") if ref_node.null?
419
420
 
420
421
  envelope_result = self.xmlSecTmplReferenceAddTransform(ref_node, self.xmlSecTransformEnvelopedGetKlass)
@@ -427,15 +428,14 @@ module XMLSecurity
427
428
  raise SignatureFailure.new("failed to create signature context") if digital_signature_context.null?
428
429
 
429
430
  digital_signature_context[:signKey] = self.xmlSecOpenSSLAppKeyLoad(private_key, :xmlSecKeyDataFormatPem, nil, nil, nil)
430
- raise SignatureFailure.new("failed to load private pem ley from #{private_key}") if digital_signature_context[:signKey].null?
431
+ raise SignatureFailure.new("failed to load private pem key from #{private_key}") if digital_signature_context[:signKey].null?
431
432
 
432
- if self.xmlSecKeySetName(digital_signature_context[:signKey], File.basename(private_key)) < 0
433
- raise SignatureFailure.new("failed to set key name for key of #{private_key}")
433
+ if self.xmlSecOpenSSLAppKeyCertLoad(digital_signature_context[:signKey], certificate, :xmlSecKeyDataFormatPem) < 0
434
+ raise SignatureFailure.new("failed to load public cert from #{certificate}")
434
435
  end
435
436
 
436
- if self.xmlSecTmplKeyInfoAddKeyName(key_info_node, nil).null?
437
- raise SignatureFailure.new("failed to add key info")
438
- end
437
+ x509_data_node = self.xmlSecTmplKeyInfoAddX509Data(key_info_node)
438
+ raise SignatureFailure.new("failed to add <dsig:X509Data/> node") if x509_data_node.null?
439
439
 
440
440
  if self.xmlSecDSigCtxSign(digital_signature_context, sign_node) < 0
441
441
  raise SignatureFailure.new("signature failed!")
@@ -443,9 +443,10 @@ module XMLSecurity
443
443
 
444
444
  ptr = FFI::MemoryPointer.new(:pointer, 1)
445
445
  sizeptr = FFI::MemoryPointer.new(:pointer, 1)
446
- self.xmlDocDumpFormatMemory(doc, ptr, sizeptr, 1)
446
+ self.xmlDocDumpFormatMemory(doc, ptr, sizeptr, 0)
447
447
  strptr = ptr.read_pointer
448
- result = strptr.null? ? nil : strptr.read_string
448
+
449
+ return strptr.null? ? nil : strptr.read_string
449
450
  ensure
450
451
  ptr.free if defined?(ptr) && ptr
451
452
  sizeptr.free if defined?(sizeptr) && sizeptr
@@ -454,4 +455,25 @@ module XMLSecurity
454
455
  self.xmlFree(strptr) if defined?(strptr) && strptr && !strptr.null?
455
456
  end
456
457
 
458
+
459
+ #
460
+ # Register 'ID' as an XML id attribute so we can properly sign/validate
461
+ # signatures with references of the form:
462
+ #
463
+ # <dsig:Reference URI="#IdOfElementImSigning" />
464
+ #
465
+ # Which refer to another element in the same document like:
466
+ #
467
+ # <elem ID="IdOfElementImSigning" />
468
+ #
469
+ # For more information see:
470
+ #
471
+ # http://www.aleksey.com/xmlsec/faq.html#section_3_4
472
+ #
473
+ def self.register_xml_id_attribute(doc, root)
474
+ idary = FFI::MemoryPointer.new(:pointer, 2)
475
+ idary[0].put_pointer(0, FFI::MemoryPointer.from_string("ID"))
476
+ idary[1].put_pointer(0, nil)
477
+ XMLSecurity.xmlSecAddIDs(doc, root, idary)
478
+ end
457
479
  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.21"
3
+ s.version = "0.1.22"
4
4
 
5
5
  s.authors = ["OneLogin LLC", "Bracken", "Zach", "Cody", "Jeremy", "Paul"]
6
- s.date = %q{2013-03-07}
6
+ s.date = %q{2013-05-07}
7
7
  s.extra_rdoc_files = [
8
8
  "LICENSE"
9
9
  ]
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.1.21
4
+ version: 0.1.22
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2013-03-07 00:00:00.000000000 Z
17
+ date: 2013-05-07 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: libxml-ruby
@@ -95,3 +95,4 @@ signing_key:
95
95
  specification_version: 3
96
96
  summary: Ruby library for SAML service providers
97
97
  test_files: []
98
+ has_rdoc: