Module: Samlr::Tools
- Defined in:
- lib/samlr/tools.rb,
lib/samlr/tools/timestamp.rb,
lib/samlr/tools/request_builder.rb,
lib/samlr/tools/metadata_builder.rb,
lib/samlr/tools/response_builder.rb,
lib/samlr/tools/certificate_builder.rb,
lib/samlr/tools/logout_request_builder.rb,
lib/samlr/tools/logout_response_builder.rb
Defined Under Namespace
Modules: LogoutRequestBuilder, LogoutResponseBuilder, RequestBuilder, ResponseBuilder, Timestamp Classes: CertificateBuilder, MetadataBuilder
Constant Summary collapse
- SHA_MAP =
{ 1 => OpenSSL::Digest::SHA1, 256 => OpenSSL::Digest::SHA256, 384 => OpenSSL::Digest::SHA384, 512 => OpenSSL::Digest::SHA512 }
Class Method Summary collapse
-
.algorithm(value) ⇒ Object
Convert algorithm attribute value to Ruby implementation.
-
.canonicalize(xml, options = {}) ⇒ Object
Accepts a document and optionally :path => xpath, :c14n_mode => c14n_mode.
-
.decode(string) ⇒ Object
CGI unescapes, Base64 decodes and inflates a string.
-
.encode(string) ⇒ Object
Deflates, Base64 encodes and CGI escapes a string.
- .inflate(data) ⇒ Object
-
.parse(data, compressed: false) ⇒ Object
Tries to parse the SAML request, returns nil if no data passed.
-
.uuid ⇒ Object
Generate an xs:NCName conforming UUID.
-
.validate(options = {}) ⇒ Object
Validate a SAML request or response against an XSD.
- .validate!(options = {}) ⇒ Object
Class Method Details
.algorithm(value) ⇒ Object
Convert algorithm attribute value to Ruby implementation
25 26 27 28 29 30 31 |
# File 'lib/samlr/tools.rb', line 25 def self.algorithm(value) if value =~ /sha(\d+)$/ implementation = SHA_MAP[$1.to_i] end implementation || OpenSSL::Digest::SHA1 end |
.canonicalize(xml, options = {}) ⇒ Object
Accepts a document and optionally :path => xpath, :c14n_mode => c14n_mode
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/samlr/tools.rb', line 34 def self.canonicalize(xml, = {}) = { :c14n_mode => C14N }.merge() document = Nokogiri::XML(xml) { |c| c.strict.noblanks } if path = [:path] node = document.at(path, NS_MAP) else node = document end node.canonicalize([:c14n_mode], [:namespaces]) end |
.decode(string) ⇒ Object
CGI unescapes, Base64 decodes and inflates a string
61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/samlr/tools.rb', line 61 def self.decode(string) unescaped = CGI.unescape(string) decoded = Base64.decode64(unescaped) inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) inflated = inflater.inflate(decoded) inflater.finish inflater.close inflated end |
.encode(string) ⇒ Object
Deflates, Base64 encodes and CGI escapes a string
53 54 55 56 57 58 |
# File 'lib/samlr/tools.rb', line 53 def self.encode(string) deflated = Zlib::Deflate.deflate(string, 9)[2..-5] encoded = Base64.encode64(deflated) escaped = CGI.escape(encoded) escaped end |
.inflate(data) ⇒ Object
136 137 138 139 140 141 142 143 |
# File 'lib/samlr/tools.rb', line 136 def self.inflate(data) inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) decoded = inflater.inflate(data) inflater.finish inflater.close decoded end |
.parse(data, compressed: false) ⇒ Object
Tries to parse the SAML request, returns nil if no data passed. First, it assumes it to be Base64 encoded. If this fails, it subsequently attempts to parse the raw input as select IdP’s send that rather than a Base64 encoded value
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/samlr/tools.rb', line 113 def self.parse(data, compressed: false) return unless data decoded = Base64.decode64(data) decoded = self.inflate(decoded) if compressed begin doc = Nokogiri::XML(decoded) { |config| config.strict } rescue Nokogiri::XML::SyntaxError => e begin doc = Nokogiri::XML(data) { |config| config.strict } rescue raise Samlr::FormatError.new(e.) end end begin Samlr::Tools.validate!(:document => doc) rescue Samlr::SamlrError => e Samlr.logger.warn("Accepting non schema conforming response: #{e.}, #{e.details}") raise e unless Samlr.validation_mode == :log end doc end |
.uuid ⇒ Object
Generate an xs:NCName conforming UUID
48 49 50 |
# File 'lib/samlr/tools.rb', line 48 def self.uuid "samlr-#{UUIDTools::UUID.}" end |
.validate(options = {}) ⇒ Object
Validate a SAML request or response against an XSD. Supply either :path or :document in the options and a :schema (defaults to SAML validation)
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 |
# File 'lib/samlr/tools.rb', line 79 def self.validate( = {}) document = [:document] || File.read([:path]) schema = .fetch(:schema, SAML_SCHEMA) bang = .fetch(:bang, false) if document.is_a?(Nokogiri::XML::Document) xml = document else xml = Nokogiri::XML(document) { |c| c.strict } end # All bundled schemas are using relative schemaLocation. This means we'll have to # change working directory to find them during validation. Dir.chdir(Samlr.schema_location) do if schema.is_a?(Nokogiri::XML::Schema) xsd = schema else xsd = Nokogiri::XML::Schema(File.read(schema)) end result = xsd.validate(xml) if bang && result.length != 0 raise Samlr::FormatError.new("Schema validation failed", "XSD validation errors: #{result.join(", ")}") else result.length == 0 end end end |
.validate!(options = {}) ⇒ Object
73 74 75 |
# File 'lib/samlr/tools.rb', line 73 def self.validate!( = {}) validate(.merge(:bang => true)) end |