-
-
Notifications
You must be signed in to change notification settings - Fork 590
Expand file tree
/
Copy pathxml.rb
More file actions
155 lines (135 loc) · 5.73 KB
/
xml.rb
File metadata and controls
155 lines (135 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# frozen_string_literal: true
require 'openssl'
require 'nokogiri'
require 'digest/sha1'
require 'digest/sha2'
module RubySaml
# XML Signature and Canonicalization algorithms.
# @api private
module XML
extend self
# XML namespaces
# @api private
C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#'
DSIG = 'http://www.w3.org/2000/09/xmldsig#'
XENC = 'http://www.w3.org/2001/04/xmlenc#'
XSI = 'http://www.w3.org/2001/XMLSchema-instance'
# Encryption algorithms
# @api private
RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
RSA_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha224'
RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
DSA_SHA256 = 'http://www.w3.org/2009/xmldsig11#dsa-sha256'
ECDSA_SHA1 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1'
ECDSA_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224'
ECDSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256'
ECDSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384'
ECDSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512'
SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1'
SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#sha224'
SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256'
SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#sha384'
SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512'
ENVELOPED_SIG = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
# SAML namespaces
# @api private
NS_METADATA = 'urn:oasis:names:tc:SAML:2.0:metadata'
NS_ASSERTION = 'urn:oasis:names:tc:SAML:2.0:assertion'
NS_PROTOCOL = 'urn:oasis:names:tc:SAML:2.0:protocol'
# @api private
NOKOGIRI_OPTIONS = Nokogiri::XML::ParseOptions::STRICT |
Nokogiri::XML::ParseOptions::NONET
# Safely load the SAML Message XML.
# @param document [String | Nokogiri::XML::Document] The message to be loaded
# @param check_malformed_doc [Boolean] check_malformed_doc Enable or Disable the check for malformed XML
# @return [Nokogiri::XML::Document] The nokogiri document
# @raise [StandardError] If there was a problem loading the SAML Message XML
def safe_load_xml(document, check_malformed_doc: true)
doc_str = document.to_s
raise StandardError.new('Dangerous XML detected. No Doctype nodes allowed') if doc_str.include?('<!DOCTYPE')
begin
doc = Nokogiri::XML(doc_str) do |config|
config.options = NOKOGIRI_OPTIONS
end
rescue StandardError => e
raise StandardError.new(e.message)
rescue SyntaxError => e
raise StandardError.new(e.message) if check_malformed_doc && e.message != 'Empty document'
end
if doc.is_a?(Nokogiri::XML::Document)
StandardError.new('Dangerous XML detected. No Doctype nodes allowed') if doc.internal_subset
StandardError.new("There were XML errors when parsing: #{doc.errors}") if check_malformed_doc && !doc.errors.empty?
end
doc
end
def copy_xml(noko)
Nokogiri::XML(noko.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)) do |config|
config.options = NOKOGIRI_OPTIONS
end
end
# Lookup XML canonicalization algorithm.
# @api private
def canon_algorithm(element, default: true)
case get_algorithm_attr(element)
when %r{\Ahttp://www\.w3\.org/TR/2001/REC-xml-c14n-20010315#?(?:WithComments)?\z}i
Nokogiri::XML::XML_C14N_1_0
when %r{\Ahttp://www\.w3\.org/2006/12/xml-c14n11#?(?:WithComments)?\z}i
Nokogiri::XML::XML_C14N_1_1
when %r{\Ahttp://www\.w3\.org/2001/10/xml-exc-c14n#?(?:WithComments)?\z}i
Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
else
Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0 if default
end
end
# Lookup XML signature algorithm.
# @api private
def signature_algorithm(element)
alg = get_algorithm_attr(element)
match_data = alg&.downcase&.match(/(?:\A|#)(rsa|dsa|ecdsa)-(sha\d+)\z/i) || {}
key_alg = match_data[1]
hash_alg = match_data[2]
key = case key_alg
when 'rsa' then OpenSSL::PKey::RSA
when 'dsa' then OpenSSL::PKey::DSA
when 'ecdsa' then OpenSSL::PKey::EC
else # rubocop:disable Lint/DuplicateBranch
# TODO: raise ArgumentError.new("Invalid key algorithm: #{alg}")
OpenSSL::PKey::RSA
end
[key, hash_algorithm(hash_alg)]
end
# Lookup XML digest hashing algorithm.
# @api private
def hash_algorithm(element)
alg = get_algorithm_attr(element)
hash_alg = alg&.downcase&.match(/(?:\A|[#-])(sha\d+)\z/i)&.[](1)
case hash_alg
when 'sha1' then OpenSSL::Digest::SHA1
when 'sha224' then OpenSSL::Digest::SHA224
when 'sha256' then OpenSSL::Digest::SHA256
when 'sha384' then OpenSSL::Digest::SHA384
when 'sha512' then OpenSSL::Digest::SHA512
else # rubocop:disable Lint/DuplicateBranch
# TODO: raise ArgumentError.new("Invalid hash algorithm: #{alg}")
OpenSSL::Digest::SHA256
end
end
private
def get_algorithm_attr(element)
if element.is_a?(Nokogiri::XML::Element)
element['Algorithm']
elsif element
element
end
end
end
end
require 'ruby_saml/xml/decoder'
require 'ruby_saml/xml/decryptor'
require 'ruby_saml/xml/document_signer'
require 'ruby_saml/xml/signed_document_info'
require 'ruby_saml/xml/signed_document_validator'
require 'ruby_saml/xml/deprecated'