sepafm 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +14 -30
- data/.ruby-version +1 -1
- data/.travis.yml +15 -0
- data/Gemfile +1 -1
- data/LICENSE +16 -4
- data/README.md +180 -319
- data/Rakefile +7 -2
- data/lib/sepa/application_request.rb +100 -131
- data/lib/sepa/application_response.rb +28 -84
- data/lib/sepa/attribute_checks.rb +169 -0
- data/lib/sepa/banks/danske/danske_response.rb +19 -0
- data/lib/sepa/banks/danske/soap_danske.rb +132 -0
- data/lib/sepa/banks/nordea/nordea_response.rb +20 -0
- data/lib/sepa/banks/nordea/soap_nordea.rb +51 -0
- data/lib/sepa/client.rb +72 -60
- data/lib/sepa/error_messages.rb +15 -0
- data/lib/sepa/response.rb +88 -85
- data/lib/sepa/soap_builder.rb +51 -341
- data/lib/sepa/utilities.rb +132 -0
- data/lib/sepa/version.rb +1 -1
- data/lib/sepa/xml_schemas/PKIFactory.xsd +334 -0
- data/lib/sepa/xml_schemas/xml_id.xsd +9 -0
- data/lib/sepa/xml_templates/application_request/create_certificate.xml +15 -10
- data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +13 -9
- data/lib/sepa/xml_templates/application_request/download_file.xml +32 -30
- data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -27
- data/lib/sepa/xml_templates/application_request/encrypted_request.xml +22 -0
- data/lib/sepa/xml_templates/application_request/get_certificate.xml +9 -8
- data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -24
- data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -27
- data/lib/sepa/xml_templates/soap/create_certificate.xml +17 -15
- data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +15 -13
- data/lib/sepa/xml_templates/soap/download_file.xml +19 -15
- data/lib/sepa/xml_templates/soap/download_file_list.xml +19 -15
- data/lib/sepa/xml_templates/soap/get_certificate.xml +2 -1
- data/lib/sepa/xml_templates/soap/get_user_info.xml +19 -15
- data/lib/sepa/xml_templates/soap/header.xml +48 -37
- data/lib/sepa/xml_templates/soap/upload_file.xml +19 -15
- data/lib/sepafm.rb +20 -18
- data/{sepa.gemspec → sepafm.gemspec} +10 -9
- data/test/sepa/banks/danske/danske_cert_response_test.rb +52 -0
- data/test/sepa/banks/danske/danske_cert_soap_builder_test.rb +100 -0
- data/test/sepa/banks/danske/danske_generic_soap_builder_test.rb +278 -0
- data/test/sepa/banks/danske/danske_get_bank_cert_test.rb +111 -0
- data/{lib/sepa/danske_testing/keys/danske_encryption.crt → test/sepa/banks/danske/keys/bank_encryption_cert.pem} +0 -0
- data/test/sepa/{danske_test_keys/danskeroot.pem → banks/danske/keys/bank_root_cert.pem} +1 -1
- data/test/sepa/banks/danske/keys/bank_signing_cert.pem +24 -0
- data/test/sepa/banks/danske/keys/danske_encryption.crt +24 -0
- data/test/sepa/banks/danske/keys/enc_private_key.pem +27 -0
- data/test/sepa/{danske_test_keys → banks/danske/keys}/encryption_pkcs.csr +0 -0
- data/test/sepa/banks/danske/keys/own_enc_cert.pem +21 -0
- data/test/sepa/banks/danske/keys/own_signing_cert.pem +22 -0
- data/test/sepa/{danske_test_keys → banks/danske/keys}/signing_key.pem +0 -0
- data/test/sepa/{danske_test_keys → banks/danske/keys}/signing_pkcs.csr +0 -0
- data/test/sepa/banks/danske/keys/signing_private_key.pem +27 -0
- data/test/sepa/banks/danske/responses/create_cert.xml +38 -0
- data/test/sepa/banks/danske/responses/get_bank_cert.xml +37 -0
- data/{lib/sepa/nordea_testing → test/sepa/banks/nordea}/keys/nordea.crt +0 -4
- data/test/sepa/{nordea_test_keys → banks/nordea/keys}/nordea.key +0 -3
- data/test/sepa/{nordea_test_keys → banks/nordea/keys}/root_cert.cer +0 -0
- data/test/sepa/{nordea_test_keys → banks/nordea/keys}/testcert.csr +0 -0
- data/test/sepa/banks/nordea/nordea_application_request_test.rb +252 -0
- data/test/sepa/{application_response_test.rb → banks/nordea/nordea_application_response_test.rb} +40 -46
- data/test/sepa/banks/nordea/nordea_cert_application_request_test.rb +72 -0
- data/test/sepa/banks/nordea/nordea_cert_request_soap_builder_test.rb +65 -0
- data/test/sepa/banks/nordea/nordea_generic_soap_builder_test.rb +280 -0
- data/test/sepa/banks/nordea/nordea_response_test.rb +116 -0
- data/test/sepa/banks/nordea/responses/df_ktl.xml +45 -0
- data/test/sepa/{test_files/test_responses/df.xml → banks/nordea/responses/df_tito.xml} +1 -1
- data/test/sepa/{test_files/test_responses → banks/nordea/responses}/dfl.xml +0 -0
- data/test/sepa/banks/nordea/responses/gbc.xml +15 -0
- data/test/sepa/banks/nordea/responses/gc.xml +49 -0
- data/test/sepa/{test_files/test_responses → banks/nordea/responses}/gui.xml +0 -0
- data/test/sepa/{test_files/test_responses → banks/nordea/responses}/uf.xml +0 -0
- data/test/sepa/client_test.rb +156 -302
- data/test/sepa/fixtures.rb +214 -0
- data/test/sepa/sepa_test.rb +3 -13
- data/test/sepa/test_files/{invalid.wsdl → invalid_wsdl.wsdl} +0 -0
- data/test/test_helper.rb +29 -3
- metadata +140 -116
- data/lib/danske_get_bank_certificate_test.rb +0 -15
- data/lib/sepa/custom_exceptions.rb +0 -2
- data/lib/sepa/filedescriptor.rb +0 -7
- data/lib/sepa/filetypeservice.rb +0 -6
- data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
- data/lib/sepa/nordea_testing/keys/nordea.key +0 -19
- data/lib/sepa/nordea_testing/response/content_053.xml +0 -998
- data/lib/sepa/nordea_testing/response/content_054.xml +0 -1
- data/lib/sepa/nordea_testing/response/download_file_response.xml +0 -14
- data/lib/sepa/nordea_testing/response/download_filelist_response.xml +0 -14
- data/lib/sepa/nordea_testing/response/get_user_info_response.xml +0 -14
- data/lib/sepa/nordea_testing/response/upload_file_response.xml +0 -14
- data/lib/sepa/payload.rb +0 -109
- data/lib/sepa/payment.rb +0 -97
- data/lib/sepa/sender_verifier.rb +0 -15
- data/lib/sepa/signature.rb +0 -7
- data/lib/sepa/soap_danske.rb +0 -47
- data/lib/sepa/soap_nordea.rb +0 -68
- data/lib/sepa/transaction.rb +0 -178
- data/lib/sepa/userfiletype.rb +0 -16
- data/lib/sepa/xml_parser.rb +0 -291
- data/lib/sepa_client_testing_mika.rb +0 -32
- data/lib/sepa_client_testing_tiere.rb +0 -257
- data/test/sepa/application_request_test.rb +0 -423
- data/test/sepa/cert_application_request_test.rb +0 -99
- data/test/sepa/nordea_cert_request_soap_builder_test.rb +0 -112
- data/test/sepa/nordea_generic_soap_builder_test.rb +0 -427
- data/test/sepa/nordea_test_keys/nordea.crt +0 -27
- data/test/sepa/payload_test.rb +0 -297
- data/test/sepa/payment_test.rb +0 -198
- data/test/sepa/response_test.rb +0 -269
- data/test/sepa/transaction_test.rb +0 -362
- data/test/sepa/user_file_type_test.rb +0 -21
- data/test/sepa/xml_parser_test.rb +0 -73
@@ -1,182 +1,151 @@
|
|
1
1
|
module Sepa
|
2
2
|
class ApplicationRequest
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@file_reference = params[:file_reference]
|
13
|
-
|
14
|
-
@private_key, @cert, @pin, @service, @csr, @hmac,
|
15
|
-
@bank_root_cert_serial,@request_id = ''
|
16
|
-
|
17
|
-
# Set values for the previously defined attributes
|
18
|
-
initialize_required_fields_per_request(params)
|
3
|
+
include Utilities
|
4
|
+
|
5
|
+
def initialize(params = {})
|
6
|
+
# Set all params as instance variables
|
7
|
+
params.each do |key, value|
|
8
|
+
instance_variable_set("@#{key}", value)
|
9
|
+
end
|
10
|
+
|
11
|
+
@ar = load_body_template AR_TEMPLATE_PATH
|
19
12
|
end
|
20
13
|
|
21
|
-
def
|
22
|
-
|
14
|
+
def to_xml
|
15
|
+
set_common_nodes
|
23
16
|
set_nodes_contents
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
17
|
+
process_signature
|
18
|
+
@ar.to_xml
|
19
|
+
end
|
28
20
|
|
29
|
-
|
21
|
+
def to_base64
|
22
|
+
Base64.encode64(to_xml)
|
30
23
|
end
|
31
24
|
|
32
|
-
|
25
|
+
def to_nokogiri
|
26
|
+
Nokogiri::XML to_xml
|
27
|
+
end
|
33
28
|
|
34
|
-
|
35
|
-
generic_commands = [:get_user_info, :upload_file, :download_file,
|
36
|
-
:download_file_list]
|
29
|
+
private
|
37
30
|
|
38
|
-
|
39
|
-
|
40
|
-
@private_key = params.fetch(:private_key)
|
41
|
-
@cert = params.fetch(:cert)
|
42
|
-
when :get_certificate
|
43
|
-
@service = params[:service]
|
44
|
-
@pin = params[:pin]
|
45
|
-
@csr = params[:csr]
|
46
|
-
@hmac = create_hmac_seal(@pin,@csr)
|
47
|
-
when :get_bank_certificate
|
48
|
-
@pin = params[:pin]
|
49
|
-
@request_id = params[:request_id]
|
50
|
-
@bank_root_cert_serial = params[:bank_root_cert_serial]
|
51
|
-
end
|
31
|
+
def set_node(node, value)
|
32
|
+
@ar.at_css(node).content = value
|
52
33
|
end
|
53
34
|
|
54
|
-
def
|
55
|
-
|
56
|
-
:get_user_info, :upload_file, :download_file,
|
57
|
-
:get_bank_certificate]
|
58
|
-
unless valid_commands.include?(command)
|
59
|
-
fail ArgumentError, "You didn't provide a proper command. " \
|
60
|
-
"Acceptable values are #{valid_commands.inspect}"
|
61
|
-
else
|
62
|
-
command
|
63
|
-
end
|
35
|
+
def set_node_b(node, value)
|
36
|
+
set_node node, Base64.encode64(value)
|
64
37
|
end
|
65
|
-
# Loads the application request template according to the command
|
66
|
-
def load_template(command)
|
67
|
-
template_dir = File.expand_path('../xml_templates/application_request',
|
68
|
-
__FILE__)
|
69
38
|
|
70
|
-
|
39
|
+
def pretty_command
|
40
|
+
@command.to_s.split(/[\W_]/).map {|c| c.capitalize}.join
|
41
|
+
end
|
71
42
|
|
43
|
+
def set_nodes_contents
|
44
|
+
case @command
|
45
|
+
when :create_certificate
|
46
|
+
set_create_certificate_nodes
|
72
47
|
when :get_certificate
|
73
|
-
|
48
|
+
set_get_certificate_nodes
|
74
49
|
when :download_file_list
|
75
|
-
|
76
|
-
when :get_user_info
|
77
|
-
path = "#{template_dir}/get_user_info.xml"
|
78
|
-
when :upload_file
|
79
|
-
path = "#{template_dir}/upload_file.xml"
|
50
|
+
set_download_file_list_nodes
|
80
51
|
when :download_file
|
81
|
-
|
52
|
+
set_download_file_nodes
|
53
|
+
when :upload_file
|
54
|
+
set_upload_file_nodes
|
82
55
|
when :get_bank_certificate
|
83
|
-
|
56
|
+
set_get_bank_certificate_nodes
|
84
57
|
end
|
58
|
+
end
|
85
59
|
|
86
|
-
|
60
|
+
def set_download_file_nodes
|
61
|
+
set_download_file_list_nodes
|
62
|
+
set_node("FileReference", @file_reference)
|
87
63
|
end
|
88
64
|
|
65
|
+
def set_get_bank_certificate_nodes
|
66
|
+
set_node("elem|BankRootCertificateSerialNo", @bank_root_cert_serial)
|
67
|
+
set_node("elem|Timestamp", iso_time)
|
68
|
+
set_node("elem|RequestId", @request_id)
|
69
|
+
end
|
89
70
|
|
90
|
-
def
|
91
|
-
@
|
71
|
+
def set_upload_file_nodes
|
72
|
+
set_node_b("Content", @content)
|
73
|
+
set_node("FileType", @file_type)
|
74
|
+
set_node("TargetId", @target_id)
|
92
75
|
end
|
93
76
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
set_node("Environment", @environment)
|
100
|
-
set_node("SoftwareId", "Sepa Transfer Library version #{VERSION}")
|
101
|
-
set_node("Command",
|
102
|
-
@command.to_s.split(/[\W_]/).map {|c| c.capitalize}.join)
|
103
|
-
end
|
77
|
+
def set_download_file_list_nodes
|
78
|
+
set_node("Status", @status)
|
79
|
+
set_node("TargetId", @target_id)
|
80
|
+
set_node("FileType", @file_type)
|
81
|
+
end
|
104
82
|
|
105
|
-
|
83
|
+
def set_get_certificate_nodes
|
84
|
+
set_node("Service", @service)
|
85
|
+
set_node("Content", format_cert_request(@csr))
|
86
|
+
set_node("HMAC", hmac(@pin, csr_to_binary(@csr)))
|
87
|
+
end
|
106
88
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
set_node("Status", @status)
|
117
|
-
set_node("TargetId", @target_id)
|
118
|
-
set_node("FileType", @file_type)
|
119
|
-
set_node("FileReference", @file_reference)
|
120
|
-
when :upload_file
|
121
|
-
set_node("Content", Base64.encode64(@content))
|
122
|
-
set_node("FileType", @file_type)
|
123
|
-
set_node("TargetId", @target_id)
|
124
|
-
when :get_bank_certificate
|
125
|
-
set_node("elem|BankRootCertificateSerialNo", @bank_root_cert_serial)
|
126
|
-
set_node("elem|Timestamp", Time.now.iso8601)
|
127
|
-
set_node("elem|RequestId", @request_id)
|
128
|
-
end
|
89
|
+
def set_create_certificate_nodes
|
90
|
+
set_node("tns|CustomerId", @customer_id)
|
91
|
+
set_node("tns|KeyGeneratorType", @key_generator_type)
|
92
|
+
set_node("tns|EncryptionCertPKCS10", format_cert_request(@encryption_cert_pkcs10))
|
93
|
+
set_node("tns|SigningCertPKCS10", format_cert_request(@signing_cert_pkcs10))
|
94
|
+
set_node("tns|Timestamp", iso_time)
|
95
|
+
set_node("tns|RequestId", @request_id)
|
96
|
+
set_node("tns|Environment", @environment)
|
97
|
+
set_node("tns|PIN", @pin)
|
129
98
|
end
|
130
99
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
100
|
+
def set_common_nodes
|
101
|
+
return if @command == :get_bank_certificate
|
102
|
+
return if @command == :create_certificate
|
103
|
+
|
104
|
+
set_node("CustomerId", @customer_id)
|
105
|
+
set_node("Timestamp", iso_time)
|
106
|
+
set_node("Environment", @environment)
|
107
|
+
set_node("SoftwareId", "Sepa Transfer Library version #{VERSION}")
|
108
|
+
set_node("Command", pretty_command)
|
134
109
|
end
|
135
110
|
|
136
|
-
def remove_node(
|
137
|
-
|
111
|
+
def remove_node(node, xmlns)
|
112
|
+
@ar.at_css("xmlns|#{node}", 'xmlns' => xmlns).remove
|
138
113
|
end
|
139
114
|
|
140
|
-
def add_node_to_root(
|
141
|
-
|
115
|
+
def add_node_to_root(node)
|
116
|
+
@ar.root.add_child(node)
|
142
117
|
end
|
143
118
|
|
144
|
-
def calculate_digest
|
119
|
+
def calculate_digest
|
145
120
|
sha1 = OpenSSL::Digest::SHA1.new
|
146
|
-
Base64.encode64(sha1.digest(
|
121
|
+
Base64.encode64(sha1.digest(@ar.canonicalize))
|
147
122
|
end
|
148
123
|
|
149
124
|
def add_value_to_signature(node, value)
|
150
|
-
|
151
|
-
|
152
|
-
node.content = value
|
125
|
+
sig = @ar.at_css("dsig|#{node}", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#')
|
126
|
+
sig.content = value
|
153
127
|
end
|
154
128
|
|
155
|
-
def calculate_signature
|
129
|
+
def calculate_signature
|
156
130
|
sha1 = OpenSSL::Digest::SHA1.new
|
157
|
-
node = @ar.at_css("dsig|SignedInfo",
|
158
|
-
|
159
|
-
signature = private_key.sign(sha1, node.canonicalize)
|
131
|
+
node = @ar.at_css("dsig|SignedInfo", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#')
|
132
|
+
signature = @private_key.sign(sha1, node.canonicalize)
|
160
133
|
Base64.encode64(signature)
|
161
134
|
end
|
162
135
|
|
163
|
-
def format_cert(cert)
|
164
|
-
cert = cert.to_s
|
165
|
-
cert = cert.split('-----BEGIN CERTIFICATE-----')[1]
|
166
|
-
cert = cert.split('-----END CERTIFICATE-----')[0]
|
167
|
-
cert.gsub!(/\s+/, "")
|
168
|
-
end
|
169
|
-
|
170
136
|
def process_signature
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
137
|
+
# No signature for Certificate Requests
|
138
|
+
return if @command == :get_certificate
|
139
|
+
return if @command == :get_bank_certificate
|
140
|
+
return if @command == :create_certificate
|
141
|
+
|
142
|
+
signature_node = remove_node('Signature', 'http://www.w3.org/2000/09/xmldsig#')
|
143
|
+
digest = calculate_digest
|
144
|
+
add_node_to_root(signature_node)
|
176
145
|
add_value_to_signature('DigestValue', digest)
|
177
|
-
|
178
|
-
add_value_to_signature('
|
179
|
-
add_value_to_signature('X509Certificate',format_cert(@cert))
|
146
|
+
add_value_to_signature('SignatureValue', calculate_signature)
|
147
|
+
add_value_to_signature('X509Certificate', format_cert(@cert))
|
180
148
|
end
|
149
|
+
|
181
150
|
end
|
182
151
|
end
|
@@ -1,123 +1,67 @@
|
|
1
1
|
module Sepa
|
2
2
|
class ApplicationResponse
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
3
|
+
include ActiveModel::Validations
|
4
|
+
include Utilities
|
5
|
+
|
6
|
+
attr_accessor :ar, :certificate
|
7
|
+
|
8
|
+
validate :response_must_validate_against_schema
|
9
|
+
validate :validate_document_format
|
10
|
+
|
11
|
+
def initialize(app_resp)
|
12
|
+
self.ar = app_resp
|
13
|
+
self.certificate = extract_cert(ar, 'X509Certificate', 'http://www.w3.org/2000/09/xmldsig#')
|
15
14
|
end
|
16
15
|
|
17
|
-
# Checks that the hash value reported in the signature matches the actual
|
18
|
-
# one.
|
16
|
+
# Checks that the hash value reported in the signature matches the actual one.
|
19
17
|
def hashes_match?
|
20
|
-
|
18
|
+
are = ar.clone
|
21
19
|
|
22
|
-
digest_value =
|
20
|
+
digest_value = are.at_css(
|
23
21
|
'xmlns|DigestValue',
|
24
22
|
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
25
23
|
).content.strip
|
26
24
|
|
27
|
-
|
25
|
+
are.at_css(
|
28
26
|
"xmlns|Signature",
|
29
27
|
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
30
28
|
).remove
|
31
29
|
|
32
|
-
actual_digest = calculate_digest(
|
30
|
+
actual_digest = calculate_digest(are)
|
33
31
|
|
34
|
-
if digest_value == actual_digest
|
35
|
-
true
|
36
|
-
else
|
37
|
-
false
|
38
|
-
end
|
39
|
-
end
|
32
|
+
return true if digest_value == actual_digest
|
40
33
|
|
41
|
-
|
42
|
-
def certificate
|
43
|
-
cert_value = @ar.at_css(
|
44
|
-
'xmlns|X509Certificate',
|
45
|
-
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
46
|
-
).content.gsub(/\s+/, "")
|
47
|
-
|
48
|
-
cert = process_cert_value(cert_value)
|
49
|
-
|
50
|
-
begin
|
51
|
-
OpenSSL::X509::Certificate.new(cert)
|
52
|
-
rescue => e
|
53
|
-
fail OpenSSL::X509::CertificateError,
|
54
|
-
"The certificate embedded in the application response could not be " \
|
55
|
-
"processed. It's most likely corrupted. " \
|
56
|
-
"OpenSSL had this to say: #{e}."
|
57
|
-
end
|
34
|
+
false
|
58
35
|
end
|
59
36
|
|
60
|
-
# Checks that the signature is signed with the private key of the
|
61
|
-
# certificate's public key.
|
37
|
+
# Checks that the signature is signed with the private key of the certificate's public key.
|
62
38
|
def signature_is_valid?
|
63
|
-
node =
|
64
|
-
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#')
|
39
|
+
node = ar.at_css('xmlns|SignedInfo', 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#')
|
65
40
|
|
66
41
|
node = node.canonicalize
|
67
42
|
|
68
|
-
signature =
|
43
|
+
signature = ar.at_css(
|
69
44
|
'xmlns|SignatureValue',
|
70
45
|
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
71
46
|
).content
|
72
47
|
|
73
48
|
signature = Base64.decode64(signature)
|
74
49
|
|
50
|
+
# Return true or false
|
75
51
|
certificate.public_key.verify(OpenSSL::Digest::SHA1.new, signature, node)
|
76
52
|
end
|
77
53
|
|
78
|
-
# Checks that the certificate in the application response is signed with the
|
79
|
-
# private key of the public key of the certificate as parameter.
|
80
|
-
def cert_is_trusted?(root_cert)
|
81
|
-
if root_cert.subject == certificate.issuer
|
82
|
-
certificate.verify(root_cert.public_key)
|
83
|
-
else
|
84
|
-
fail SecurityError,
|
85
|
-
"The issuer of the certificate doesn't match the subject of the " \
|
86
|
-
"root certificate."
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
54
|
private
|
91
55
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
canon_node = node.canonicalize(
|
96
|
-
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
97
|
-
inclusive_namespaces=nil,with_comments=false
|
98
|
-
)
|
99
|
-
|
100
|
-
Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
|
101
|
-
end
|
102
|
-
|
103
|
-
def valid_against_ar_schema?(doc)
|
104
|
-
schemas_path = File.expand_path('../../../lib/sepa/xml_schemas',
|
105
|
-
__FILE__)
|
106
|
-
|
107
|
-
Dir.chdir(schemas_path) do
|
108
|
-
xsd = Nokogiri::XML::Schema(IO.read('application_response.xsd'))
|
109
|
-
xsd.valid?(doc)
|
56
|
+
def validate_document_format
|
57
|
+
unless ar.respond_to?(:canonicalize)
|
58
|
+
errors.add(:base, 'Document must be a Nokogiri XML file')
|
110
59
|
end
|
111
60
|
end
|
112
61
|
|
113
|
-
|
114
|
-
|
115
|
-
# can read it.
|
116
|
-
def process_cert_value(cert_value)
|
117
|
-
cert = "-----BEGIN CERTIFICATE-----\n"
|
118
|
-
cert += cert_value.to_s.gsub(/\s+/, "").scan(/.{1,64}/).join("\n")
|
119
|
-
cert += "\n"
|
120
|
-
cert += "-----END CERTIFICATE-----"
|
62
|
+
def response_must_validate_against_schema
|
63
|
+
check_validity_against_schema(ar, 'application_response.xsd')
|
121
64
|
end
|
65
|
+
|
122
66
|
end
|
123
67
|
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module Sepa
|
2
|
+
module AttributeChecks
|
3
|
+
include ErrorMessages
|
4
|
+
|
5
|
+
def allowed_commands
|
6
|
+
case bank
|
7
|
+
when :nordea
|
8
|
+
[:get_certificate, :get_user_info, :download_file_list, :download_file, :upload_file]
|
9
|
+
when :danske
|
10
|
+
[:get_bank_certificate, :get_user_info, :download_file_list, :download_file,
|
11
|
+
:upload_file, :create_certificate]
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_command
|
18
|
+
errors.add(:command, "Invalid command") unless allowed_commands.include? command
|
19
|
+
end
|
20
|
+
|
21
|
+
def check_keys
|
22
|
+
return if [:get_certificate, :get_bank_certificate, :create_certificate].include? command
|
23
|
+
|
24
|
+
begin
|
25
|
+
OpenSSL::PKey::RSA.new private_key
|
26
|
+
rescue
|
27
|
+
errors.add(:private_key, "Invalid private key")
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
OpenSSL::X509::Certificate.new cert
|
32
|
+
rescue
|
33
|
+
errors.add(:cert, "Invalid certificate")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_signing_cert
|
38
|
+
return unless command == :create_certificate
|
39
|
+
|
40
|
+
unless cert_request_valid?(signing_cert_pkcs10)
|
41
|
+
errors.add(:signing_cert_pkcs10, SIGNING_CERT_REQUEST_ERROR_MESSAGE)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_encryption_cert_request
|
46
|
+
return unless command == :create_certificate
|
47
|
+
|
48
|
+
unless cert_request_valid?(encryption_cert_pkcs10)
|
49
|
+
errors.add(:encryption_cert_pkcs10, ENCRYPTION_CERT_REQUEST_ERROR_MESSAGE)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def wsdl
|
54
|
+
case bank
|
55
|
+
when :nordea
|
56
|
+
if command == :get_certificate
|
57
|
+
file = "wsdl_nordea_cert.xml"
|
58
|
+
else
|
59
|
+
file = "wsdl_nordea.xml"
|
60
|
+
end
|
61
|
+
when :danske
|
62
|
+
if [:get_bank_certificate, :create_certificate].include? command
|
63
|
+
file = "wsdl_danske_cert.xml"
|
64
|
+
else
|
65
|
+
file = "wsdl_danske.xml"
|
66
|
+
end
|
67
|
+
else
|
68
|
+
return nil
|
69
|
+
end
|
70
|
+
|
71
|
+
"#{WSDL_PATH}/#{file}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def check_wsdl
|
75
|
+
return unless wsdl.present?
|
76
|
+
|
77
|
+
xsd = Nokogiri::XML::Schema(File.read(SCHEMA_FILE))
|
78
|
+
wsdl_file = File.read(wsdl)
|
79
|
+
xml = Nokogiri::XML(wsdl_file)
|
80
|
+
|
81
|
+
unless xsd.valid?(xml)
|
82
|
+
errors.add(:wsdl, "Invalid wsdl file")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_file_type
|
87
|
+
return unless [:upload_file, :download_file_list, :download_file].include? command
|
88
|
+
|
89
|
+
if file_type.nil? || file_type.size > 35
|
90
|
+
errors.add(:file_type, FILE_TYPE_ERROR_MESSAGE)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def check_target_id
|
95
|
+
return if [:get_certificate, :create_certificate, :get_bank_certificate].include? command
|
96
|
+
|
97
|
+
check_presence_and_length(:target_id, 80, TARGET_ID_ERROR_MESSAGE)
|
98
|
+
end
|
99
|
+
|
100
|
+
def check_presence_and_length(attribute, length, error_message)
|
101
|
+
if send(attribute).nil? || send(attribute).size > length
|
102
|
+
errors.add(attribute, error_message)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def check_content
|
107
|
+
return unless command == :upload_file
|
108
|
+
|
109
|
+
errors.add(:content, CONTENT_ERROR_MESSAGE) if content.nil?
|
110
|
+
end
|
111
|
+
|
112
|
+
def check_pin
|
113
|
+
return unless command == :create_certificate
|
114
|
+
|
115
|
+
check_presence_and_length(:pin, 10, PIN_ERROR_MESSAGE)
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_bank_root_cert_serial
|
119
|
+
return unless command == :get_bank_certificate
|
120
|
+
|
121
|
+
unless bank_root_cert_serial && bank_root_cert_serial.length.between?(1, 64)
|
122
|
+
errors.add(:bank_root_cert_serial, "Invalid bank root certificate serial")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def check_environment
|
127
|
+
return if command == :get_bank_certificate
|
128
|
+
|
129
|
+
environments = ['PRODUCTION', 'TEST', 'customertest']
|
130
|
+
|
131
|
+
unless environments.include? environment
|
132
|
+
errors.add(:environment, ENVIRONMENT_ERROR_MESSAGE)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def check_customer_id
|
137
|
+
return if command == :get_bank_certificate
|
138
|
+
|
139
|
+
unless customer_id && customer_id.length.between?(1, 16)
|
140
|
+
errors.add(:customer_id, CUSTOMER_ID_ERROR_MESSAGE)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def check_enc_cert
|
145
|
+
return unless command == :create_certificate
|
146
|
+
|
147
|
+
errors.add(:enc_cert, ENCRYPTION_CERT_ERROR_MESSAGE) unless enc_cert
|
148
|
+
end
|
149
|
+
|
150
|
+
def check_status
|
151
|
+
return unless [:download_file_list, :download_file].include? command
|
152
|
+
|
153
|
+
statuses = ['NEW', 'DOWNLOADED', 'ALL']
|
154
|
+
|
155
|
+
unless status && statuses.include?(status)
|
156
|
+
errors.add :status, STATUS_ERROR_MESSAGE
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def check_file_reference
|
161
|
+
return unless command == :download_file
|
162
|
+
|
163
|
+
unless file_reference && file_reference.length <= 32
|
164
|
+
errors.add :file_reference, FILE_REFERENCE_ERROR_MESSAGE
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sepa
|
2
|
+
class DanskeResponse < Response
|
3
|
+
attr_reader :bank_encryption_cert, :bank_signing_cert, :bank_root_cert, :own_encryption_cert,
|
4
|
+
:own_signing_cert, :ca_certificate
|
5
|
+
|
6
|
+
# Namespace used in danske bank certificate responses and requests
|
7
|
+
TNS = 'http://danskebank.dk/PKI/PKIFactoryService/elements'
|
8
|
+
|
9
|
+
def initialize(response, command: nil)
|
10
|
+
super
|
11
|
+
@bank_encryption_cert = extract_cert(soap, 'BankEncryptionCert', TNS)
|
12
|
+
@bank_signing_cert = extract_cert(soap, 'BankSigningCert', TNS)
|
13
|
+
@bank_root_cert = extract_cert(soap, 'BankRootCert', TNS)
|
14
|
+
@own_encryption_cert = extract_cert(soap, 'EncryptionCert', TNS)
|
15
|
+
@own_signing_cert = extract_cert(soap, 'SigningCert', TNS)
|
16
|
+
@ca_certificate = extract_cert(soap, 'CACert', TNS)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|