spid-es 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +15 -0
  2. data/.document +5 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE +19 -0
  6. data/README.md +124 -0
  7. data/Rakefile +41 -0
  8. data/lib/schemas/saml20assertion_schema.xsd +283 -0
  9. data/lib/schemas/saml20protocol_schema.xsd +302 -0
  10. data/lib/schemas/xenc_schema.xsd +146 -0
  11. data/lib/schemas/xmldsig_schema.xsd +318 -0
  12. data/lib/spid/ruby-saml/authrequest.rb +196 -0
  13. data/lib/spid/ruby-saml/coding.rb +34 -0
  14. data/lib/spid/ruby-saml/logging.rb +26 -0
  15. data/lib/spid/ruby-saml/logout_request.rb +126 -0
  16. data/lib/spid/ruby-saml/logout_response.rb +132 -0
  17. data/lib/spid/ruby-saml/metadata.rb +353 -0
  18. data/lib/spid/ruby-saml/request.rb +81 -0
  19. data/lib/spid/ruby-saml/response.rb +202 -0
  20. data/lib/spid/ruby-saml/settings.rb +72 -0
  21. data/lib/spid/ruby-saml/validation_error.rb +7 -0
  22. data/lib/spid/ruby-saml/version.rb +5 -0
  23. data/lib/spid-es.rb +14 -0
  24. data/lib/xml_security.rb +165 -0
  25. data/spid-es.gemspec +23 -0
  26. data/test/certificates/certificate1 +12 -0
  27. data/test/logoutrequest_test.rb +98 -0
  28. data/test/request_test.rb +53 -0
  29. data/test/response_test.rb +219 -0
  30. data/test/responses/adfs_response_sha1.xml +46 -0
  31. data/test/responses/adfs_response_sha256.xml +46 -0
  32. data/test/responses/adfs_response_sha384.xml +46 -0
  33. data/test/responses/adfs_response_sha512.xml +46 -0
  34. data/test/responses/no_signature_ns.xml +48 -0
  35. data/test/responses/open_saml_response.xml +56 -0
  36. data/test/responses/response1.xml.base64 +1 -0
  37. data/test/responses/response2.xml.base64 +79 -0
  38. data/test/responses/response3.xml.base64 +66 -0
  39. data/test/responses/response4.xml.base64 +93 -0
  40. data/test/responses/response5.xml.base64 +102 -0
  41. data/test/responses/response_with_ampersands.xml +139 -0
  42. data/test/responses/response_with_ampersands.xml.base64 +93 -0
  43. data/test/responses/simple_saml_php.xml +71 -0
  44. data/test/responses/wrapped_response_2.xml.base64 +150 -0
  45. data/test/settings_test.rb +43 -0
  46. data/test/test_helper.rb +65 -0
  47. data/test/xml_security_test.rb +123 -0
  48. metadata +158 -0
@@ -0,0 +1,318 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE schema
3
+ PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
4
+ [
5
+ <!ATTLIST schema
6
+ xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
7
+ <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
8
+ <!ENTITY % p ''>
9
+ <!ENTITY % s ''>
10
+ ]>
11
+
12
+ <!-- Schema for XML Signatures
13
+ http://www.w3.org/2000/09/xmldsig#
14
+ $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
15
+
16
+ Copyright 2001 The Internet Society and W3C (Massachusetts Institute
17
+ of Technology, Institut National de Recherche en Informatique et en
18
+ Automatique, Keio University). All Rights Reserved.
19
+ http://www.w3.org/Consortium/Legal/
20
+
21
+ This document is governed by the W3C Software License [1] as described
22
+ in the FAQ [2].
23
+
24
+ [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
25
+ [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
26
+ -->
27
+
28
+
29
+ <schema xmlns="http://www.w3.org/2001/XMLSchema"
30
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
31
+ targetNamespace="http://www.w3.org/2000/09/xmldsig#"
32
+ version="0.1" elementFormDefault="qualified">
33
+
34
+ <!-- Basic Types Defined for Signatures -->
35
+
36
+ <simpleType name="CryptoBinary">
37
+ <restriction base="base64Binary">
38
+ </restriction>
39
+ </simpleType>
40
+
41
+ <!-- Start Signature -->
42
+
43
+ <element name="Signature" type="ds:SignatureType"/>
44
+ <complexType name="SignatureType">
45
+ <sequence>
46
+ <element ref="ds:SignedInfo"/>
47
+ <element ref="ds:SignatureValue"/>
48
+ <element ref="ds:KeyInfo" minOccurs="0"/>
49
+ <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
50
+ </sequence>
51
+ <attribute name="Id" type="ID" use="optional"/>
52
+ </complexType>
53
+
54
+ <element name="SignatureValue" type="ds:SignatureValueType"/>
55
+ <complexType name="SignatureValueType">
56
+ <simpleContent>
57
+ <extension base="base64Binary">
58
+ <attribute name="Id" type="ID" use="optional"/>
59
+ </extension>
60
+ </simpleContent>
61
+ </complexType>
62
+
63
+ <!-- Start SignedInfo -->
64
+
65
+ <element name="SignedInfo" type="ds:SignedInfoType"/>
66
+ <complexType name="SignedInfoType">
67
+ <sequence>
68
+ <element ref="ds:CanonicalizationMethod"/>
69
+ <element ref="ds:SignatureMethod"/>
70
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
71
+ </sequence>
72
+ <attribute name="Id" type="ID" use="optional"/>
73
+ </complexType>
74
+
75
+ <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
76
+ <complexType name="CanonicalizationMethodType" mixed="true">
77
+ <sequence>
78
+ <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
79
+ <!-- (0,unbounded) elements from (1,1) namespace -->
80
+ </sequence>
81
+ <attribute name="Algorithm" type="anyURI" use="required"/>
82
+ </complexType>
83
+
84
+ <element name="SignatureMethod" type="ds:SignatureMethodType"/>
85
+ <complexType name="SignatureMethodType" mixed="true">
86
+ <sequence>
87
+ <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
88
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
89
+ <!-- (0,unbounded) elements from (1,1) external namespace -->
90
+ </sequence>
91
+ <attribute name="Algorithm" type="anyURI" use="required"/>
92
+ </complexType>
93
+
94
+ <!-- Start Reference -->
95
+
96
+ <element name="Reference" type="ds:ReferenceType"/>
97
+ <complexType name="ReferenceType">
98
+ <sequence>
99
+ <element ref="ds:Transforms" minOccurs="0"/>
100
+ <element ref="ds:DigestMethod"/>
101
+ <element ref="ds:DigestValue"/>
102
+ </sequence>
103
+ <attribute name="Id" type="ID" use="optional"/>
104
+ <attribute name="URI" type="anyURI" use="optional"/>
105
+ <attribute name="Type" type="anyURI" use="optional"/>
106
+ </complexType>
107
+
108
+ <element name="Transforms" type="ds:TransformsType"/>
109
+ <complexType name="TransformsType">
110
+ <sequence>
111
+ <element ref="ds:Transform" maxOccurs="unbounded"/>
112
+ </sequence>
113
+ </complexType>
114
+
115
+ <element name="Transform" type="ds:TransformType"/>
116
+ <complexType name="TransformType" mixed="true">
117
+ <choice minOccurs="0" maxOccurs="unbounded">
118
+ <any namespace="##other" processContents="lax"/>
119
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
120
+ <element name="XPath" type="string"/>
121
+ </choice>
122
+ <attribute name="Algorithm" type="anyURI" use="required"/>
123
+ </complexType>
124
+
125
+ <!-- End Reference -->
126
+
127
+ <element name="DigestMethod" type="ds:DigestMethodType"/>
128
+ <complexType name="DigestMethodType" mixed="true">
129
+ <sequence>
130
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
131
+ </sequence>
132
+ <attribute name="Algorithm" type="anyURI" use="required"/>
133
+ </complexType>
134
+
135
+ <element name="DigestValue" type="ds:DigestValueType"/>
136
+ <simpleType name="DigestValueType">
137
+ <restriction base="base64Binary"/>
138
+ </simpleType>
139
+
140
+ <!-- End SignedInfo -->
141
+
142
+ <!-- Start KeyInfo -->
143
+
144
+ <element name="KeyInfo" type="ds:KeyInfoType"/>
145
+ <complexType name="KeyInfoType" mixed="true">
146
+ <choice maxOccurs="unbounded">
147
+ <element ref="ds:KeyName"/>
148
+ <element ref="ds:KeyValue"/>
149
+ <element ref="ds:RetrievalMethod"/>
150
+ <element ref="ds:X509Data"/>
151
+ <element ref="ds:PGPData"/>
152
+ <element ref="ds:SPKIData"/>
153
+ <element ref="ds:MgmtData"/>
154
+ <any processContents="lax" namespace="##other"/>
155
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
156
+ </choice>
157
+ <attribute name="Id" type="ID" use="optional"/>
158
+ </complexType>
159
+
160
+ <element name="KeyName" type="string"/>
161
+ <element name="MgmtData" type="string"/>
162
+
163
+ <element name="KeyValue" type="ds:KeyValueType"/>
164
+ <complexType name="KeyValueType" mixed="true">
165
+ <choice>
166
+ <element ref="ds:DSAKeyValue"/>
167
+ <element ref="ds:RSAKeyValue"/>
168
+ <any namespace="##other" processContents="lax"/>
169
+ </choice>
170
+ </complexType>
171
+
172
+ <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
173
+ <complexType name="RetrievalMethodType">
174
+ <sequence>
175
+ <element ref="ds:Transforms" minOccurs="0"/>
176
+ </sequence>
177
+ <attribute name="URI" type="anyURI"/>
178
+ <attribute name="Type" type="anyURI" use="optional"/>
179
+ </complexType>
180
+
181
+ <!-- Start X509Data -->
182
+
183
+ <element name="X509Data" type="ds:X509DataType"/>
184
+ <complexType name="X509DataType">
185
+ <sequence maxOccurs="unbounded">
186
+ <choice>
187
+ <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
188
+ <element name="X509SKI" type="base64Binary"/>
189
+ <element name="X509SubjectName" type="string"/>
190
+ <element name="X509Certificate" type="base64Binary"/>
191
+ <element name="X509CRL" type="base64Binary"/>
192
+ <any namespace="##other" processContents="lax"/>
193
+ </choice>
194
+ </sequence>
195
+ </complexType>
196
+
197
+ <complexType name="X509IssuerSerialType">
198
+ <sequence>
199
+ <element name="X509IssuerName" type="string"/>
200
+ <element name="X509SerialNumber" type="integer"/>
201
+ </sequence>
202
+ </complexType>
203
+
204
+ <!-- End X509Data -->
205
+
206
+ <!-- Begin PGPData -->
207
+
208
+ <element name="PGPData" type="ds:PGPDataType"/>
209
+ <complexType name="PGPDataType">
210
+ <choice>
211
+ <sequence>
212
+ <element name="PGPKeyID" type="base64Binary"/>
213
+ <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
214
+ <any namespace="##other" processContents="lax" minOccurs="0"
215
+ maxOccurs="unbounded"/>
216
+ </sequence>
217
+ <sequence>
218
+ <element name="PGPKeyPacket" type="base64Binary"/>
219
+ <any namespace="##other" processContents="lax" minOccurs="0"
220
+ maxOccurs="unbounded"/>
221
+ </sequence>
222
+ </choice>
223
+ </complexType>
224
+
225
+ <!-- End PGPData -->
226
+
227
+ <!-- Begin SPKIData -->
228
+
229
+ <element name="SPKIData" type="ds:SPKIDataType"/>
230
+ <complexType name="SPKIDataType">
231
+ <sequence maxOccurs="unbounded">
232
+ <element name="SPKISexp" type="base64Binary"/>
233
+ <any namespace="##other" processContents="lax" minOccurs="0"/>
234
+ </sequence>
235
+ </complexType>
236
+
237
+ <!-- End SPKIData -->
238
+
239
+ <!-- End KeyInfo -->
240
+
241
+ <!-- Start Object (Manifest, SignatureProperty) -->
242
+
243
+ <element name="Object" type="ds:ObjectType"/>
244
+ <complexType name="ObjectType" mixed="true">
245
+ <sequence minOccurs="0" maxOccurs="unbounded">
246
+ <any namespace="##any" processContents="lax"/>
247
+ </sequence>
248
+ <attribute name="Id" type="ID" use="optional"/>
249
+ <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
250
+ <attribute name="Encoding" type="anyURI" use="optional"/>
251
+ </complexType>
252
+
253
+ <element name="Manifest" type="ds:ManifestType"/>
254
+ <complexType name="ManifestType">
255
+ <sequence>
256
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
257
+ </sequence>
258
+ <attribute name="Id" type="ID" use="optional"/>
259
+ </complexType>
260
+
261
+ <element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
262
+ <complexType name="SignaturePropertiesType">
263
+ <sequence>
264
+ <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
265
+ </sequence>
266
+ <attribute name="Id" type="ID" use="optional"/>
267
+ </complexType>
268
+
269
+ <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
270
+ <complexType name="SignaturePropertyType" mixed="true">
271
+ <choice maxOccurs="unbounded">
272
+ <any namespace="##other" processContents="lax"/>
273
+ <!-- (1,1) elements from (1,unbounded) namespaces -->
274
+ </choice>
275
+ <attribute name="Target" type="anyURI" use="required"/>
276
+ <attribute name="Id" type="ID" use="optional"/>
277
+ </complexType>
278
+
279
+ <!-- End Object (Manifest, SignatureProperty) -->
280
+
281
+ <!-- Start Algorithm Parameters -->
282
+
283
+ <simpleType name="HMACOutputLengthType">
284
+ <restriction base="integer"/>
285
+ </simpleType>
286
+
287
+ <!-- Start KeyValue Element-types -->
288
+
289
+ <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
290
+ <complexType name="DSAKeyValueType">
291
+ <sequence>
292
+ <sequence minOccurs="0">
293
+ <element name="P" type="ds:CryptoBinary"/>
294
+ <element name="Q" type="ds:CryptoBinary"/>
295
+ </sequence>
296
+ <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
297
+ <element name="Y" type="ds:CryptoBinary"/>
298
+ <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
299
+ <sequence minOccurs="0">
300
+ <element name="Seed" type="ds:CryptoBinary"/>
301
+ <element name="PgenCounter" type="ds:CryptoBinary"/>
302
+ </sequence>
303
+ </sequence>
304
+ </complexType>
305
+
306
+ <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
307
+ <complexType name="RSAKeyValueType">
308
+ <sequence>
309
+ <element name="Modulus" type="ds:CryptoBinary"/>
310
+ <element name="Exponent" type="ds:CryptoBinary"/>
311
+ </sequence>
312
+ </complexType>
313
+
314
+ <!-- End KeyValue Element-types -->
315
+
316
+ <!-- End Signature -->
317
+
318
+ </schema>
@@ -0,0 +1,196 @@
1
+ require "base64"
2
+ require "uuid"
3
+ require "zlib"
4
+ require "cgi"
5
+ require "rexml/document"
6
+ require "rexml/xpath"
7
+ require "rubygems"
8
+ require "addressable/uri"
9
+
10
+ module Spid::Saml
11
+ include REXML
12
+ class Authrequest
13
+ # a few symbols for SAML class names
14
+ HTTP_POST = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
15
+ HTTP_GET = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
16
+
17
+ attr_accessor :uuid, :request
18
+
19
+ def initialize( settings )
20
+ @settings = settings
21
+ @request_params = Hash.new
22
+ end
23
+
24
+ def create(params = {})
25
+ uuid = "_" + UUID.new.generate
26
+ self.uuid = uuid
27
+ time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
28
+ # Create AuthnRequest root element using REXML
29
+ request_doc = REXML::Document.new
30
+ request_doc.context[:attribute_quote] = :quote
31
+ root = request_doc.add_element "saml2p:AuthnRequest", { "xmlns:saml2p" => "urn:oasis:names:tc:SAML:2.0:protocol" }
32
+ root.attributes['ID'] = uuid
33
+ root.attributes['IssueInstant'] = time
34
+ root.attributes['Version'] = "2.0"
35
+ root.attributes['ProtocolBinding'] = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
36
+ root.attributes['AttributeConsumingServiceIndex'] = "1"
37
+ root.attributes['ForceAuthn'] = "false"
38
+ #root.attributes['IsPassive'] = "false"
39
+ #usato AssertionConsumerServiceURL e ProtocolBinding in alternativa, pag 8 regole tecniche
40
+ #root.attributes['AssertionConsumerServiceIndex'] = 1
41
+
42
+ # Conditionally defined elements based on settings
43
+ if @settings.assertion_consumer_service_url != nil
44
+ root.attributes["AssertionConsumerServiceURL"] = @settings.assertion_consumer_service_url
45
+ end
46
+
47
+ if @settings.destination_service_url != nil
48
+ root.attributes["Destination"] = @settings.destination_service_url
49
+ end
50
+
51
+ if @settings.issuer != nil
52
+ issuer = root.add_element "saml2:Issuer", { "xmlns:saml2" => "urn:oasis:names:tc:SAML:2.0:assertion" }
53
+ issuer.attributes['NameQualifier'] = @settings.issuer
54
+ issuer.attributes['Format'] = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
55
+ issuer.text = @settings.issuer
56
+ end
57
+
58
+ #opzionale
59
+ if @settings.sp_name_qualifier != nil
60
+ subject = root.add_element "saml2:Subject", { "xmlns:saml2" => "urn:oasis:names:tc:SAML:2.0:assertion" }
61
+ name_id = subject.add_element "saml2:NameID", { "xmlns:saml2" => "urn:oasis:names:tc:SAML:2.0:assertion" }
62
+ name_id.attributes['Format'] = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
63
+ name_id.attributes['NameQualifier'] = @settings.sp_name_qualifier
64
+ end
65
+
66
+
67
+
68
+ if @settings.name_identifier_format != nil
69
+ root.add_element "saml2p:NameIDPolicy", {
70
+ # Might want to make AllowCreate a setting?
71
+ #{}"AllowCreate" => "true",
72
+ "Format" => @settings.name_identifier_format[1],
73
+ "SPNameQualifier" => @settings.sp_name_qualifier
74
+ }
75
+ end
76
+
77
+ # BUG fix here -- if an authn_context is defined, add the tags with an "exact"
78
+ # match required for authentication to succeed. If this is not defined,
79
+ # the IdP will choose default rules for authentication. (Shibboleth IdP)
80
+ if @settings.authn_context != nil
81
+ requested_context = root.add_element "saml2p:RequestedAuthnContext", {
82
+ "Comparison" => "exact"
83
+ }
84
+ context_class = []
85
+ @settings.authn_context.each_with_index{ |context, index|
86
+ context_class[index] = requested_context.add_element "saml2:AuthnContextClassRef", {
87
+ "xmlns:saml2" => "urn:oasis:names:tc:SAML:2.0:assertion"
88
+ }
89
+ context_class[index].text = context
90
+ }
91
+
92
+ end
93
+
94
+ if @settings.requester_identificator != nil
95
+ requester_identificator = root.add_element "saml2p:Scoping", {
96
+ "ProxyCount" => "0"
97
+ }
98
+ identificators = []
99
+ @settings.requester_identificator.each_with_index{ |requester, index|
100
+ identificators[index] = requester_identificator.add_element "saml2p:RequesterID"
101
+ identificators[index].text = requester
102
+ }
103
+
104
+ end
105
+
106
+ request_doc << REXML::XMLDecl.new(version='1.0', encoding='UTF-8')
107
+ ret = ""
108
+ # pretty print the XML so IdP administrators can easily see what the SP supports
109
+ request_doc.write(ret, 1)
110
+
111
+ @request = ""
112
+ request_doc.write(@request)
113
+
114
+ #Logging.debug "Created AuthnRequest: #{@request}"
115
+
116
+ return self
117
+
118
+ end
119
+
120
+ # get the IdP metadata, and select the appropriate SSO binding
121
+ # that we can support. Currently this is HTTP-Redirect and HTTP-POST
122
+ # but more could be added in the future
123
+ def binding_select
124
+ # first check if we're still using the old hard coded method for
125
+ # backwards compatability
126
+ if @settings.idp_metadata == nil && @settings.idp_sso_target_url != nil
127
+ @URL = @settings.idp_sso_target_url
128
+ return "GET", content_get
129
+ end
130
+ # grab the metadata
131
+ metadata = Metadata::new
132
+ meta_doc = metadata.get_idp_metadata(@settings)
133
+
134
+ # first try POST
135
+ sso_element = REXML::XPath.first(meta_doc,
136
+ "/EntityDescriptor/IDPSSODescriptor/SingleSignOnService[@Binding='#{HTTP_POST}']")
137
+ if sso_element
138
+ @URL = sso_element.attributes["Location"]
139
+ #Logging.debug "binding_select: POST to #{@URL}"
140
+ return "POST", content_post
141
+ end
142
+
143
+ # next try GET
144
+ sso_element = REXML::XPath.first(meta_doc,
145
+ "/EntityDescriptor/IDPSSODescriptor/SingleSignOnService[@Binding='#{HTTP_GET}']")
146
+ if sso_element
147
+ @URL = sso_element.attributes["Location"]
148
+ Logging.debug "binding_select: GET from #{@URL}"
149
+ return "GET", content_get
150
+ end
151
+ # other types we might want to add in the future: SOAP, Artifact
152
+ end
153
+
154
+ # construct the the parameter list on the URL and return
155
+ def content_get
156
+ # compress GET requests to try and stay under that 8KB request limit
157
+ deflated_request = Zlib::Deflate.deflate(@request, 9)[2..-5]
158
+ # strict_encode64() isn't available? sub out the newlines
159
+ @request_params["SAMLRequest"] = Base64.encode64(deflated_request).gsub(/\n/, "")
160
+
161
+ Logging.debug "SAMLRequest=#{@request_params["SAMLRequest"]}"
162
+ uri = Addressable::URI.parse(@URL)
163
+ if uri.query_values == nil
164
+ uri.query_values = @request_params
165
+ else
166
+ # solution to stevenwilkin's parameter merge
167
+ uri.query_values = @request_params.merge(uri.query_values)
168
+ end
169
+ url = uri.to_s
170
+ #Logging.debug "Sending to URL #{url}"
171
+ return url
172
+ end
173
+ # construct an HTML form (POST) and return the content
174
+ def content_post
175
+ # POST requests seem to bomb out when they're deflated
176
+ # and they probably don't need to be compressed anyway
177
+ @request_params["SAMLRequest"] = Base64.encode64(@request).gsub(/\n/, "")
178
+
179
+ #Logging.debug "SAMLRequest=#{@request_params["SAMLRequest"]}"
180
+ # kind of a cheesy method of building an HTML, form since we can't rely on Rails too much,
181
+ # and REXML doesn't work well with quote characters
182
+ str = "<html><body onLoad=\"document.getElementById('form').submit();\">\n"
183
+ str += "<form id='form' name='form' method='POST' action=\"#{@URL}\">\n"
184
+ # we could change this in the future to associate a temp auth session ID
185
+ str += "<input name='RelayState' value='ruby-saml' type='hidden' />\n"
186
+ @request_params.each_pair do |key, value|
187
+ str += "<input name=\"#{key}\" value=\"#{value}\" type='hidden' />\n"
188
+ #str += "<input name=\"#{key}\" value=\"#{CGI.escape(value)}\" type='hidden' />\n"
189
+ end
190
+ str += "</form></body></html>\n"
191
+
192
+ #Logging.debug "Created form:\n#{str}"
193
+ return str
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,34 @@
1
+ require "cgi"
2
+ require 'zlib'
3
+
4
+ module Spid
5
+ module Saml
6
+ module Coding
7
+ def decode(encoded)
8
+ Base64.decode64(encoded)
9
+ end
10
+
11
+ def encode(encoded)
12
+ Base64.encode64(encoded).gsub(/\n/, "")
13
+ end
14
+
15
+ def escape(unescaped)
16
+ CGI.escape(unescaped)
17
+ end
18
+
19
+ def unescape(escaped)
20
+ CGI.unescape(escaped)
21
+ end
22
+
23
+ def inflate(deflated)
24
+ zlib = Zlib::Inflate.new(-Zlib::MAX_WBITS)
25
+ zlib.inflate(deflated)
26
+ end
27
+
28
+ def deflate(inflated)
29
+ Zlib::Deflate.deflate(inflated, 9)[2..-5]
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ # Simplistic log class when we're running in Rails
2
+ module Spid
3
+ module Saml
4
+ class Logging
5
+ def self.debug(message)
6
+ return if !!ENV["ruby-saml/testing"]
7
+
8
+ if defined? Rails
9
+ Rails.logger.debug message
10
+ else
11
+ puts message
12
+ end
13
+ end
14
+
15
+ def self.info(message)
16
+ return if !!ENV["ruby-saml/testing"]
17
+
18
+ if defined? Rails
19
+ Rails.logger.info message
20
+ else
21
+ puts message
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end