sepafm 0.0.1

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.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +8 -0
  6. data/README.md +236 -0
  7. data/Rakefile +10 -0
  8. data/lib/danske_get_bank_certificate_test.rb +15 -0
  9. data/lib/sepa/application_request.rb +182 -0
  10. data/lib/sepa/application_response.rb +123 -0
  11. data/lib/sepa/client.rb +79 -0
  12. data/lib/sepa/danske_testing/keys/danske_encryption.crt +24 -0
  13. data/lib/sepa/filedescriptor.rb +7 -0
  14. data/lib/sepa/filetypeservice.rb +6 -0
  15. data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
  16. data/lib/sepa/nordea_testing/keys/nordea.crt +27 -0
  17. data/lib/sepa/nordea_testing/keys/nordea.key +19 -0
  18. data/lib/sepa/nordea_testing/response/content_053.xml +998 -0
  19. data/lib/sepa/nordea_testing/response/content_054.xml +1 -0
  20. data/lib/sepa/nordea_testing/response/download_file_response.xml +14 -0
  21. data/lib/sepa/nordea_testing/response/download_filelist_response.xml +14 -0
  22. data/lib/sepa/nordea_testing/response/get_user_info_response.xml +14 -0
  23. data/lib/sepa/nordea_testing/response/upload_file_response.xml +14 -0
  24. data/lib/sepa/response.rb +177 -0
  25. data/lib/sepa/sender_verifier.rb +15 -0
  26. data/lib/sepa/signature.rb +7 -0
  27. data/lib/sepa/soap_builder.rb +395 -0
  28. data/lib/sepa/soap_danske.rb +47 -0
  29. data/lib/sepa/soap_nordea.rb +68 -0
  30. data/lib/sepa/userfiletype.rb +16 -0
  31. data/lib/sepa/version.rb +3 -0
  32. data/lib/sepa/wsdl/wsdl_danske.xml +234 -0
  33. data/lib/sepa/wsdl/wsdl_danske_cert.xml +280 -0
  34. data/lib/sepa/wsdl/wsdl_nordea.xml +234 -0
  35. data/lib/sepa/wsdl/wsdl_nordea_cert.xml +187 -0
  36. data/lib/sepa/xml_parser.rb +291 -0
  37. data/lib/sepa/xml_schemas/application_request.xsd +135 -0
  38. data/lib/sepa/xml_schemas/application_response.xsd +311 -0
  39. data/lib/sepa/xml_schemas/cert_application_request.xsd +107 -0
  40. data/lib/sepa/xml_schemas/danske_pki.xsd +334 -0
  41. data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
  42. data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
  43. data/lib/sepa/xml_schemas/soap.xsd +126 -0
  44. data/lib/sepa/xml_schemas/wsdl.xml +310 -0
  45. data/lib/sepa/xml_schemas/xml.xsd +287 -0
  46. data/lib/sepa/xml_schemas/xmldsig-core-schema.xsd +318 -0
  47. data/lib/sepa/xml_templates/application_request/create_certificate.xml +10 -0
  48. data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +10 -0
  49. data/lib/sepa/xml_templates/application_request/download_file.xml +32 -0
  50. data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -0
  51. data/lib/sepa/xml_templates/application_request/get_certificate.xml +10 -0
  52. data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -0
  53. data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -0
  54. data/lib/sepa/xml_templates/soap/create_certificate.xml +15 -0
  55. data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +14 -0
  56. data/lib/sepa/xml_templates/soap/download_file.xml +16 -0
  57. data/lib/sepa/xml_templates/soap/download_file_list.xml +16 -0
  58. data/lib/sepa/xml_templates/soap/get_certificate.xml +13 -0
  59. data/lib/sepa/xml_templates/soap/get_user_info.xml +16 -0
  60. data/lib/sepa/xml_templates/soap/header.xml +37 -0
  61. data/lib/sepa/xml_templates/soap/upload_file.xml +16 -0
  62. data/lib/sepa.rb +21 -0
  63. data/lib/sepa_client_testing_mika.rb +32 -0
  64. data/lib/sepa_client_testing_tiere.rb +80 -0
  65. data/sepa.gemspec +29 -0
  66. data/test/sepa/application_request_test.rb +423 -0
  67. data/test/sepa/application_response_test.rb +238 -0
  68. data/test/sepa/cert_application_request_test.rb +99 -0
  69. data/test/sepa/client_test.rb +425 -0
  70. data/test/sepa/danske_test_keys/danskeroot.pem +25 -0
  71. data/test/sepa/danske_test_keys/encryption_pkcs.csr +0 -0
  72. data/test/sepa/danske_test_keys/signing_key.pem +27 -0
  73. data/test/sepa/danske_test_keys/signing_pkcs.csr +0 -0
  74. data/test/sepa/nordea_cert_request_soap_builder_test.rb +112 -0
  75. data/test/sepa/nordea_generic_soap_builder_test.rb +427 -0
  76. data/test/sepa/nordea_test_keys/nordea.crt +27 -0
  77. data/test/sepa/nordea_test_keys/nordea.key +19 -0
  78. data/test/sepa/nordea_test_keys/root_cert.cer +0 -0
  79. data/test/sepa/nordea_test_keys/testcert.csr +0 -0
  80. data/test/sepa/response_test.rb +269 -0
  81. data/test/sepa/sepa_test.rb +20 -0
  82. data/test/sepa/test_files/invalid.wsdl +1 -0
  83. data/test/sepa/test_files/test_responses/df.xml +20 -0
  84. data/test/sepa/test_files/test_responses/dfl.xml +20 -0
  85. data/test/sepa/test_files/test_responses/gui.xml +20 -0
  86. data/test/sepa/test_files/test_responses/uf.xml +20 -0
  87. data/test/sepa/user_file_type_test.rb +21 -0
  88. data/test/sepa/xml_parser_test.rb +73 -0
  89. data/test/test_helper.rb +9 -0
  90. metadata +256 -0
@@ -0,0 +1,14 @@
1
+ <c2b:ApplicationResponse xmlns:c2b="http://bxd.fi/xmldata/"><c2b:CustomerId>679155330</c2b:CustomerId><c2b:Timestamp>2010-09-10T10:20:38+02:00</c2b:Timestamp><c2b:ResponseCode>00</c2b:ResponseCode><c2b:ResponseText>OK.</c2b:ResponseText><c2b:Encrypted>false</c2b:Encrypted><c2b:Compressed>false</c2b:Compressed><c2b:UserFileTypes><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HAELASKUT</c2b:FileType><c2b:FileTypeName>E-invoice to payer FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI3329501800008512</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI5229501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI7429501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI8319503000004327</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HTMKTL</c2b:FileType><c2b:FileTypeName>Reference payments (html) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HTMKTO</c2b:FileType><c2b:FileTypeName>Account statement (html) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000012445</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000086423</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HYLLASKUT</c2b:FileType><c2b:FileTypeName>Rejected e-invoices to sender FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-00370011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>INFO</c2b:FileType><c2b:FileTypeName>Info</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId/><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>N</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>KORKO</c2b:FileType><c2b:FileTypeName>Interest</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId/><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>N</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>KTL</c2b:FileType><c2b:FileTypeName>Reference Payments FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>LAHLASKUT</c2b:FileType><c2b:FileTypeName>E-invoice from invoicer FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-00370011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>LMP300</c2b:FileType><c2b:FileTypeName>Bill Payment service FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>LMPPAL</c2b:FileType><c2b:FileTypeName>Bill payment service feedback FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>?</c2b:ServiceId><c2b:ServiceIdOwnerName>?</c2b:ServiceIdOwnerName><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText>?</c2b:ServiceIdText></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>NDCORPAYL</c2b:FileType><c2b:FileTypeName>Corporate payments - feedback FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-111111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>NDCORPAYS</c2b:FileType><c2b:FileTypeName>Corporate payments FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-111111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TITO</c2b:FileType><c2b:FileTypeName>Account Statement FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000012445</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000086423</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TS</c2b:FileType><c2b:FileTypeName>Salaries and pensions FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-123456789</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TSPAL</c2b:FileType><c2b:FileTypeName>Salaries and pensions feedback FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-123456789</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>?</c2b:ServiceId><c2b:ServiceIdOwnerName>?</c2b:ServiceIdOwnerName><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText>?</c2b:ServiceIdText></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TXTKTL</c2b:FileType><c2b:FileTypeName>Reference payments (txt) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TXTKTO</c2b:FileType><c2b:FileTypeName>Account statement (txt) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000012445</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000086423</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>VKEUR</c2b:FileType><c2b:FileTypeName>Rates of exchange</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId/><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>N</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType></c2b:UserFileTypes><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
2
+ <SignedInfo>
3
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
4
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
5
+ <Reference URI="">
6
+ <Transforms>
7
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
8
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
9
+ </Transforms>
10
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
11
+ <DigestValue>gNqDLvLt1Y3ma0hEFfZe3HR4hYg=</DigestValue>
12
+ </Reference>
13
+ </SignedInfo>
14
+ <SignatureValue>stMf9BuVXOD8XFxvJ3eTAxNfP0j/bm22YNJCpGLjN4TgRHBrS0OgY0WgG8O1TmptlGc63MyhwddGdIj9uYob7/q7uAhG1teY0bRCEvPc4uobDcZ2Umoqt66B2X4CuKIrdCeJNY/GBiSPIW3scA+y19F3rsnzIO3eUqZ7t8osyAk=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIID2TCCAsGgAwIBAgIEAKwkgTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJTRTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMSYwJAYDVQQDEx1Ob3JkZWEgQ29ycG9yYXRlIFNlcnZlciBDQSAwMTEUMBIGA1UEBRMLNTE2NDA2LTAxMjAwHhcNMDgxMDE3MTIzMDQxWhcNMTAxMDE3MTIzMDQxWjBmMQswCQYDVQQGEwJTRTEeMBwGA1UECgwVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMRIwEAYDVQQLDAlOb3JkZWEgSVQxIzAhBgNVBAMMGkZpbGUgVHJhbnNmZXIgV2ViIFNlcnZpY2VzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI78vhz4V6P2jWj4LPIbBv2GDg6DWPhMT0fD90mu+/N+P2wn5RcIyEVpxWWRyP+oDqq5bW+J0Ni0GF9qRB8aTSBXaZ3AHH+tWWwxXk10RhZ47fNH+yzF7HDHmVJ++OkOpELlmUDb5tX+m+qtdL8nkIywvTYBMOrp3lGgWw1NiBMwIDAQABo4IBDDCCAQgwCQYDVR0TBAIwADARBgNVHQ4ECgQISLk+63zpZ78wEwYDVR0jBAwwCoAIRMeT2dl7VsEwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5ub3JkZWEuc2UvU0NBMDEwDgYDVR0PAQH/BAQDAgWgMIGJBgNVHR8EgYEwfzB9oHugeYZ3bGRhcDovL2xkYXAubmIuc2UvY249Tm9yZGVhJTIwQ29ycG9yYXRlJTIwU2VydmVyJTIwQ0ElMjAwMSxvPU5vcmRlYSUyMEJhbmslMjBBQiUyMChwdWJsKSxjPVNFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBAKqnBbdpbOhhJQLasFA8wUzHciMK6ACGIIPbaxU1X/aKVIpZ+rS92OB0TcIqmcBoAXLyFmzOjNPZCxntp/xC2J1y3Sd0Nbh/6LpwNLkbleinakaR4WnRdV3u38yzC2eczAIIZj/rnxylwh++JmfOdK8/T5ynKYJYx5UoMcG8WICmBRfEWId5/5hrr7PiN5neryz0zRUnmG4r9ML0X93C59yTmjcZXoVZwxIkwfzDTZxlPT1m/sAjOCnSHHuCMmJSXXWOeYJLIOdASgVOl7x6xdKKw6uOD0F2IC1xjpB3XBYMR2jxcb6SSyAkXgBNCPUGFUUkcUOk3+KwIu2Cjp7u1Ro=</X509Certificate><X509IssuerSerial><X509IssuerName>serialNumber=516406-0120, CN=Nordea Corporate Server CA 01, O=Nordea Bank AB (publ), C=SE</X509IssuerName><X509SerialNumber>11281537</X509SerialNumber></X509IssuerSerial></X509Data></KeyInfo></Signature></c2b:ApplicationResponse>
@@ -0,0 +1,14 @@
1
+ <c2b:ApplicationResponse xmlns:c2b="http://bxd.fi/xmldata/"><c2b:CustomerId>679155330</c2b:CustomerId><c2b:Timestamp>2010-09-13T13:06:34.16+03:00</c2b:Timestamp><c2b:ResponseCode>00</c2b:ResponseCode><c2b:ResponseText>OK.</c2b:ResponseText><c2b:Encrypted>false</c2b:Encrypted><c2b:Compressed>false</c2b:Compressed><c2b:AmountTotal>2312.00</c2b:AmountTotal><c2b:TransactionCount>3</c2b:TransactionCount><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
2
+ <SignedInfo>
3
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
4
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
5
+ <Reference URI="">
6
+ <Transforms>
7
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
8
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
9
+ </Transforms>
10
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
11
+ <DigestValue>zXN3gtukcU0Hrn5fEJvhkLKMVIs=</DigestValue>
12
+ </Reference>
13
+ </SignedInfo>
14
+ <SignatureValue>ud/gAtrrxg+B28CMV/BPaRSSRqmqNdWjsnoEm3yT9avvq8MV39reVXi/RULw+lSJUQYXDFgfkRxRVUKK71T4PlrdlMK8gfqvREVvPdLXqmtdEvuGXa+YGfeRMgO+IE7mnvb9hTsZi2TBSle/w9BHjrfv1mrg0cFwCovcro5JUXw=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIID2TCCAsGgAwIBAgIEAKwkgTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJTRTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMSYwJAYDVQQDEx1Ob3JkZWEgQ29ycG9yYXRlIFNlcnZlciBDQSAwMTEUMBIGA1UEBRMLNTE2NDA2LTAxMjAwHhcNMDgxMDE3MTIzMDQxWhcNMTAxMDE3MTIzMDQxWjBmMQswCQYDVQQGEwJTRTEeMBwGA1UECgwVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMRIwEAYDVQQLDAlOb3JkZWEgSVQxIzAhBgNVBAMMGkZpbGUgVHJhbnNmZXIgV2ViIFNlcnZpY2VzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI78vhz4V6P2jWj4LPIbBv2GDg6DWPhMT0fD90mu+/N+P2wn5RcIyEVpxWWRyP+oDqq5bW+J0Ni0GF9qRB8aTSBXaZ3AHH+tWWwxXk10RhZ47fNH+yzF7HDHmVJ++OkOpELlmUDb5tX+m+qtdL8nkIywvTYBMOrp3lGgWw1NiBMwIDAQABo4IBDDCCAQgwCQYDVR0TBAIwADARBgNVHQ4ECgQISLk+63zpZ78wEwYDVR0jBAwwCoAIRMeT2dl7VsEwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5ub3JkZWEuc2UvU0NBMDEwDgYDVR0PAQH/BAQDAgWgMIGJBgNVHR8EgYEwfzB9oHugeYZ3bGRhcDovL2xkYXAubmIuc2UvY249Tm9yZGVhJTIwQ29ycG9yYXRlJTIwU2VydmVyJTIwQ0ElMjAwMSxvPU5vcmRlYSUyMEJhbmslMjBBQiUyMChwdWJsKSxjPVNFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBAKqnBbdpbOhhJQLasFA8wUzHciMK6ACGIIPbaxU1X/aKVIpZ+rS92OB0TcIqmcBoAXLyFmzOjNPZCxntp/xC2J1y3Sd0Nbh/6LpwNLkbleinakaR4WnRdV3u38yzC2eczAIIZj/rnxylwh++JmfOdK8/T5ynKYJYx5UoMcG8WICmBRfEWId5/5hrr7PiN5neryz0zRUnmG4r9ML0X93C59yTmjcZXoVZwxIkwfzDTZxlPT1m/sAjOCnSHHuCMmJSXXWOeYJLIOdASgVOl7x6xdKKw6uOD0F2IC1xjpB3XBYMR2jxcb6SSyAkXgBNCPUGFUUkcUOk3+KwIu2Cjp7u1Ro=</X509Certificate><X509IssuerSerial><X509IssuerName>serialNumber=516406-0120, CN=Nordea Corporate Server CA 01, O=Nordea Bank AB (publ), C=SE</X509IssuerName><X509SerialNumber>11281537</X509SerialNumber></X509IssuerSerial></X509Data></KeyInfo></Signature></c2b:ApplicationResponse>
@@ -0,0 +1,177 @@
1
+ module Sepa
2
+ class Response
3
+ def initialize(response)
4
+ @response = response
5
+
6
+ if !@response.respond_to?(:canonicalize)
7
+ fail ArgumentError,
8
+ "The response you provided is not a valid Nokogiri::XML file."
9
+ elsif !valid_against_schema?(@response)
10
+ fail ArgumentError,
11
+ "The response you provided doesn't validate against soap schema."
12
+ end
13
+ end
14
+
15
+ # Returns the x509 certificate embedded in the soap as an
16
+ # OpenSSL::X509::Certificate
17
+ def certificate
18
+ cert_value = @response.at_css(
19
+ 'wsse|BinarySecurityToken',
20
+ 'wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-ws' \
21
+ 'security-secext-1.0.xsd'
22
+ ).content.gsub(/\s+/, "")
23
+
24
+ cert = process_cert_value(cert_value)
25
+
26
+ begin
27
+ cert = OpenSSL::X509::Certificate.new(cert)
28
+ rescue => e
29
+ fail OpenSSL::X509::CertificateError,
30
+ "The certificate embedded to the soap response could not be process" \
31
+ "ed. It's most likely corrupted. OpenSSL had this to say: #{e}."
32
+ end
33
+ end
34
+
35
+ # Verifies that the soap's certificate is trusted.
36
+ def cert_is_trusted?(root_cert)
37
+ if root_cert.subject == certificate.issuer
38
+ certificate.verify(root_cert.public_key)
39
+ else
40
+ fail SecurityError,
41
+ "The issuer of the certificate doesn't match the subject of the roo" \
42
+ "t certificate."
43
+ end
44
+ end
45
+
46
+ # Verifies that all digest values in the response match the actual ones.
47
+ # Takes an optional verbose parameter to show which digests didn't match
48
+ # i.e. verbose: true
49
+ def hashes_match?(options = {})
50
+ digests = find_digest_values(@response)
51
+ nodes = find_nodes_to_verify(@response, digests)
52
+
53
+ verified_digests = digests.select do |uri, digest|
54
+ uri = uri.sub(/^#/, '')
55
+ digest == nodes[uri]
56
+ end
57
+
58
+ if digests == verified_digests
59
+ true
60
+ else
61
+ unverified_digests = digests.select do |uri, digest|
62
+ uri = uri.sub(/^#/, '')
63
+ digest != nodes[uri]
64
+ end
65
+
66
+ if options[:verbose]
67
+ puts "These digests failed to verify: #{unverified_digests}."
68
+ end
69
+
70
+ false
71
+ end
72
+ end
73
+
74
+ # Verifies the signature by extracting the public key from the certificate
75
+ # embedded in the soap header and verifying the signature value with that.
76
+ def signature_is_valid?
77
+ node = @response.at_css('xmlns|SignedInfo',
78
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#')
79
+
80
+ node = node.canonicalize(
81
+ mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
82
+ inclusive_namespaces=nil,with_comments=false
83
+ )
84
+
85
+ signature = @response.at_css(
86
+ 'xmlns|SignatureValue',
87
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
88
+ ).content
89
+
90
+ signature = Base64.decode64(signature)
91
+
92
+ certificate.public_key.verify(OpenSSL::Digest::SHA1.new, signature, node)
93
+ end
94
+
95
+ # Gets the application response from the response as an Nokogiri::XML
96
+ # document
97
+ def application_response
98
+ ar = @response.at_css('mod|ApplicationResponse').content
99
+ ar = Base64.decode64(ar)
100
+ Nokogiri::XML(ar)
101
+ end
102
+
103
+ private
104
+
105
+ # Finds all reference nodes with digest values in the document and returns
106
+ # a hash with uri as the key and digest as the value.
107
+ def find_digest_values(doc)
108
+ references = {}
109
+ reference_nodes = @response.css(
110
+ 'xmlns|Reference',
111
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
112
+ )
113
+
114
+ reference_nodes.each do |node|
115
+ uri = node.attr('URI')
116
+ digest_value = node.at_css(
117
+ 'xmlns|DigestValue',
118
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
119
+ ).content
120
+
121
+ references[uri] = digest_value
122
+ end
123
+
124
+ references
125
+ end
126
+
127
+ # Finds nodes to verify by comparing their id's to the uris' in the
128
+ # references hash.
129
+ def find_nodes_to_verify(doc, references)
130
+ nodes = {}
131
+ references.each do |uri, digest_value|
132
+ uri = uri.sub(/^#/, '')
133
+ node = doc.at_css(
134
+ "[wsu|Id='" + uri + "']",
135
+ 'wsu' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss' \
136
+ '-wssecurity-utility-1.0.xsd'
137
+ )
138
+
139
+ nodes[uri] = calculate_digest(node)
140
+ end
141
+
142
+ nodes
143
+ end
144
+
145
+ def calculate_digest(node)
146
+ sha1 = OpenSSL::Digest::SHA1.new
147
+
148
+ canon_node = node.canonicalize(
149
+ mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
150
+ inclusive_namespaces=nil,with_comments=false
151
+ )
152
+
153
+ Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
154
+ end
155
+
156
+ # Checks that the response is valid against soap schema.
157
+ def valid_against_schema?(doc)
158
+ schemas_path = File.expand_path('../../../lib/sepa/xml_schemas',
159
+ __FILE__)
160
+
161
+ Dir.chdir(schemas_path) do
162
+ xsd = Nokogiri::XML::Schema(IO.read('soap.xsd'))
163
+ xsd.valid?(doc)
164
+ end
165
+ end
166
+
167
+ # Takes the certificate from the response, adds begin and end
168
+ # certificate texts and splits it into multiple lines so that OpenSSL
169
+ # can read it.
170
+ def process_cert_value(cert_value)
171
+ cert = "-----BEGIN CERTIFICATE-----\n"
172
+ cert += cert_value.to_s.gsub(/\s+/, "").scan(/.{1,64}/).join("\n")
173
+ cert += "\n"
174
+ cert += "-----END CERTIFICATE-----"
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,15 @@
1
+ module Sepa
2
+ class SenderVerifier
3
+ def initialize(soap_response)
4
+ @soap_response = Nokogiri::XML(soap_response)
5
+ end
6
+
7
+ def get_digest_values
8
+ @soap_response.remove_namespaces!
9
+ digest_nodes = @soap_response.xpath("//Reference/dsig:DigestValue")
10
+ end
11
+
12
+ def calculate_digest
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Sepa
2
+ class Signature
3
+ # This class contains signature attributes, could be used to add
4
+ # functionality to confirm sender from crendentials
5
+ attr_accessor :digestValue, :signatureValue, :X509Certificate, :X509IssuerName
6
+ end
7
+ end
@@ -0,0 +1,395 @@
1
+ module Sepa
2
+ class SoapBuilder
3
+ # SoapBuilder checks and validates incoming params and creates the SOAP structure
4
+ def initialize(params)
5
+
6
+ check_params(params)
7
+ # Generate a request ID for the request
8
+ params[:request_id] = generate_request_id
9
+
10
+ # Check if the bank&command need keys/certificates/csr's
11
+ @params = initialize_certificates_and_csr(params)
12
+
13
+ check_if_bank_allows_command(@params)
14
+
15
+ @ar = ApplicationRequest.new(@params).get_as_base64
16
+
17
+ @bank = @params.fetch(:bank)
18
+ find_correct_bank_extension(@bank)
19
+
20
+ @template_path = File.expand_path('../xml_templates/soap/', __FILE__)
21
+ end
22
+
23
+ def to_xml
24
+ # Returns a complete SOAP message in xml format
25
+ find_correct_build(@params).to_xml
26
+ end
27
+
28
+ def get_ar_as_base64
29
+ @ar
30
+ end
31
+
32
+ private
33
+
34
+ def generate_request_id
35
+ reqid = SecureRandom.random_number(1000).to_s<<SecureRandom.random_number(1000).to_s
36
+ reqid
37
+ end
38
+
39
+ def find_correct_bank_extension(bank)
40
+ case bank
41
+ when :danske
42
+ self.extend(DanskeSoapRequest)
43
+ when :nordea
44
+ self.extend(NordeaSoapRequest)
45
+ end
46
+ end
47
+
48
+ # Generic building steps
49
+ def calculate_digest(doc, node)
50
+ sha1 = OpenSSL::Digest::SHA1.new
51
+
52
+ node = doc.at_css(node)
53
+
54
+ canon_node = node.canonicalize(
55
+ mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
56
+ inclusive_namespaces=nil,with_comments=false
57
+ )
58
+
59
+ Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
60
+ end
61
+
62
+ def calculate_signature(doc, node, private_key)
63
+ sha1 = OpenSSL::Digest::SHA1.new
64
+
65
+ node = doc.at_css(node)
66
+
67
+ canon_signed_info_node = node.canonicalize(
68
+ mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,inclusive_namespaces=nil,
69
+ with_comments=false
70
+ )
71
+
72
+ signature = private_key.sign(sha1, canon_signed_info_node)
73
+
74
+ Base64.encode64(signature).gsub(/\s+/, "")
75
+ end
76
+
77
+ def load_body_template(command)
78
+ case command
79
+ when :download_file_list
80
+ path = "#{@template_path}/download_file_list.xml"
81
+ when :get_user_info
82
+ path = "#{@template_path}/get_user_info.xml"
83
+ when :upload_file
84
+ path = "#{@template_path}/upload_file.xml"
85
+ when :download_file
86
+ path = "#{@template_path}/download_file.xml"
87
+ when :get_certificate
88
+ path = "#{@template_path}/get_certificate.xml"
89
+ when :get_bank_certificate
90
+ path = "#{@template_path}/danske_get_bank_certificate.xml"
91
+ end
92
+
93
+ body_template = File.open(path)
94
+ body = Nokogiri::XML(body_template)
95
+ body_template.close
96
+
97
+ body
98
+ end
99
+
100
+ def set_node(doc, node, value)
101
+ doc.at_css(node).content = value
102
+ end
103
+
104
+ def add_body_to_header(header, body)
105
+ body = body.at_css('env|Body')
106
+ header.root.add_child(body)
107
+ header
108
+ end
109
+
110
+ def extract_public_key(cert)
111
+ pkey = cert.public_key
112
+ pkey = OpenSSL::PKey::RSA.new(pkey)
113
+
114
+ pkey
115
+ end
116
+
117
+ def format_cert(cert)
118
+ cert = cert.to_s
119
+ cert = cert.split('-----BEGIN CERTIFICATE-----')[1]
120
+ cert = cert.split('-----END CERTIFICATE-----')[0]
121
+ cert.gsub!(/\s+/, "")
122
+ end
123
+
124
+ def load_header_template(template_path)
125
+ header_template = File.open("#{template_path}/header.xml")
126
+ header = Nokogiri::XML(header_template)
127
+ header_template.close
128
+ header
129
+ end
130
+
131
+ def process_header(header, body, private_key, cert)
132
+ set_node(header, 'wsu|Created', Time.now.iso8601)
133
+
134
+ set_node(header, 'wsu|Expires', (Time.now + 3600).iso8601)
135
+
136
+ timestamp_digest = calculate_digest(header,'wsu|Timestamp')
137
+ set_node(header,'dsig|Reference[URI="#dsfg8sdg87dsf678g6dsg6ds7fg"]' \
138
+ ' dsig|DigestValue', timestamp_digest)
139
+
140
+ body_digest = calculate_digest(body, 'env|Body')
141
+ set_node(header,'dsig|Reference[URI="#sdf6sa7d86f87s6df786sd87f6s8fsd'\
142
+ 'a"] dsig|DigestValue', body_digest)
143
+
144
+ signature = calculate_signature(header, 'dsig|SignedInfo', private_key)
145
+ set_node(header, 'dsig|SignatureValue', signature)
146
+
147
+ formatted_cert = format_cert(cert)
148
+ set_node(header, 'wsse|BinarySecurityToken', formatted_cert)
149
+ end
150
+
151
+ # Tries to validate the parameters or their presence.
152
+ def check_params(params)
153
+ # Universally for all
154
+ check_params_hash(params)
155
+ check_certificate_and_key_requirements(params)
156
+ check_bank(params[:bank])
157
+ check_env(params[:environment])
158
+ check_customer_id(params[:customer_id])
159
+
160
+ # Generic commands
161
+ generic_commands = [:download_file,:download_file_list,:get_user_info]
162
+
163
+ # Depending on command
164
+ case params[:command]
165
+ when :get_certificate
166
+ check_pin(params[:pin])
167
+ check_service(params[:service])
168
+ when *generic_commands
169
+ if params[:bank] == :nordea
170
+ check_lang(params[:language])
171
+ check_status(params[:status])
172
+ check_target_id(params[:target_id])
173
+ check_file_type(params[:file_type])
174
+ end
175
+ when :upload_file
176
+ check_lang(params[:language])
177
+ check_target_id(params[:target_id])
178
+ check_file_type(params[:file_type])
179
+ check_content(params[:content])
180
+ when :get_bank_certificate
181
+ if params[:bank] == :danske
182
+ # Nothing here
183
+ end
184
+ else
185
+ fail ArgumentError, "Command not supported."
186
+ end
187
+ end
188
+
189
+ def check_csr(csr)
190
+ unless csr
191
+ fail ArgumentError, "You didn't provide a certificate signing request"
192
+ end
193
+ end
194
+
195
+ def check_params_hash(params)
196
+ unless params.respond_to?(:each_pair)
197
+ fail ArgumentError, "You didn't provide a proper hash"
198
+ end
199
+ end
200
+
201
+ def check_bank(bank)
202
+ unless [:nordea, :danske].include?(bank)
203
+ fail ArgumentError, "You didn't provide a proper bank. " \
204
+ "Acceptable values are nordea OR danske."
205
+ end
206
+ end
207
+
208
+ def check_request_id(request_id)
209
+ if request_id.to_i == 0
210
+ fail ArgumentError, "Request ID must be a number and not 0"
211
+ end
212
+ end
213
+
214
+ def check_keygen_type(keygen)
215
+ unless keygen
216
+ fail ArgumentError, "You didn't provide any Key Generator Type"
217
+ end
218
+ end
219
+
220
+ def check_encryption_pkcs10(enc_cert)
221
+ unless enc_cert
222
+ fail ArgumentError, "You didn't provide Encrypting certificate PKCS10"
223
+ end
224
+ end
225
+
226
+ def check_signing_pkcs10(sig_cert)
227
+ unless sig_cert
228
+ fail ArgumentError, "You didn't provide Signing certificate PKCS10"
229
+ end
230
+ end
231
+
232
+ def check_pin(pin)
233
+ unless pin
234
+ fail ArgumentError, "You didn't provide a secret PIN"
235
+ end
236
+ end
237
+
238
+ def check_private_key(private_key)
239
+ unless private_key.respond_to?(:sign)
240
+ fail ArgumentError, "You didn't provide a proper private key. The " \
241
+ "key has to be in OpenSSL::PKey::RSA - format."
242
+ end
243
+ end
244
+
245
+ def check_cert(cert)
246
+ unless cert.respond_to?(:check_private_key)
247
+ fail ArgumentError, "You didn't provide a proper certificate. The " \
248
+ "certificate has to be in OpenSSL::X509::Certificate - format."
249
+ end
250
+ end
251
+
252
+ def check_customer_id(customer_id)
253
+ unless customer_id && customer_id.respond_to?(:to_s) &&
254
+ customer_id.length <= 16
255
+ fail ArgumentError, "You didn't provide a proper customer id"
256
+ end
257
+ end
258
+
259
+ def check_env(env)
260
+ unless ['PRODUCTION', 'TEST', 'customertest'].include?(env)
261
+ fail ArgumentError, "You didn't provide a proper environment. " \
262
+ "Acceptable values are PRODUCTION or TEST or customertest."
263
+ end
264
+ end
265
+
266
+ def check_status(status)
267
+ unless ['NEW', 'DOWNLOADED', 'ALL'].include?(status)
268
+ fail ArgumentError, "You didn't provide a proper status. " \
269
+ "Acceptable values are NEW, DOWNLOADED or ALL."
270
+ end
271
+ end
272
+
273
+ def check_target_id(target_id)
274
+ unless target_id && target_id.respond_to?(:to_s) &&
275
+ target_id.length <= 80
276
+ fail ArgumentError, "You didn't provide a proper target id"
277
+ end
278
+ end
279
+
280
+ def check_lang(lang)
281
+ unless ['FI', 'SE', 'EN'].include?(lang)
282
+ fail ArgumentError, "You didn't provide a proper language. " \
283
+ "Acceptable values are FI, SE or EN."
284
+ end
285
+ end
286
+
287
+ def check_file_type(file_type)
288
+ unless file_type && file_type.respond_to?(:to_s) &&
289
+ file_type.length <= 20
290
+ fail ArgumentError, "You didn't provide a proper file type. Check " \
291
+ "Your bank's documentation for available file types."
292
+ end
293
+ end
294
+
295
+ def check_content(content)
296
+ unless content
297
+ fail ArgumentError, "You didn't provide any content."
298
+ end
299
+ end
300
+
301
+ def check_service(service)
302
+ unless ['service', 'ISSUER', 'MATU'].include?(service)
303
+ fail ArgumentError, "You didn't provide a proper service."
304
+ end
305
+ end
306
+
307
+ def check_hmac(hmac)
308
+ unless hmac
309
+ fail ArgumentError, "You didn't provide any HMAC."
310
+ end
311
+ end
312
+
313
+ def check_if_bank_allows_command(params)
314
+ bank = params.fetch(:bank)
315
+ command = params.fetch(:command)
316
+ case bank
317
+ when :nordea
318
+ allowed_commands = [:get_certificate,:get_user_info,
319
+ :download_file_list,:download_file,:upload_file]
320
+ unless allowed_commands.include?(command)
321
+ fail ArgumentError, "You didn't provide a matching bank and service."
322
+ end
323
+ when :danske
324
+ allowed_commands = [:get_bank_certificate]
325
+ unless allowed_commands.include?(command)
326
+ fail ArgumentError, "You didn't provide a matching bank and service."
327
+ end
328
+ end
329
+ end
330
+
331
+ def check_certificate_and_key_requirements(params)
332
+ command = params[:command]
333
+ require_private_and_cert = [:get_user_info,:download_file_list,
334
+ :download_file,:upload_file]
335
+ require_nothing = [:get_bank_certificate]
336
+ require_pkcs = [:get_certificate]
337
+
338
+ case command
339
+ when *require_private_and_cert
340
+ if params[:cert_path] == nil && params[:cert_plain] == nil
341
+ fail ArgumentError, "You must provide a path to the certificate " \
342
+ "or certificate in plain text"
343
+ end
344
+ if params[:private_key_path] == nil && params[:private_key_plain] == nil
345
+ fail ArgumentError, "You must provide a path to your private key " \
346
+ "or private key in plain text"
347
+ end
348
+ when *require_nothing
349
+ when *require_pkcs
350
+ if params[:csr_path] == nil && params[:csr_plain] == nil
351
+ fail ArgumentError, "You must provide a path to the CSR or CSR in plain text"
352
+ end
353
+ end
354
+ end
355
+
356
+ def initialize_certificates_and_csr(params)
357
+ begin
358
+ command = params[:command]
359
+ require_private_and_cert = [:get_user_info,:download_file_list,
360
+ :download_file,:upload_file]
361
+ require_nothing = [:get_bank_certificate]
362
+ require_pkcs = [:get_certificate]
363
+
364
+ case command
365
+ when *require_private_and_cert
366
+ if params[:cert_path] != nil
367
+ params[:cert] = OpenSSL::X509::Certificate.new(File.read(params.fetch(:cert_path)))
368
+ elsif params[:cert_plain] != nil
369
+ params[:cert] = OpenSSL::X509::Certificate.new(params.fetch(:cert_plain))
370
+ end
371
+ if params[:private_key_path] != nil
372
+ params[:private_key] = OpenSSL::PKey::RSA.new(File.read(params.fetch(:private_key_path)))
373
+ elsif params[:private_key_plain] != nil
374
+ params[:private_key] = OpenSSL::PKey::RSA.new(params.fetch(:private_key_plain))
375
+ end
376
+ check_private_key(params[:private_key])
377
+ check_cert(params[:cert])
378
+ when *require_nothing
379
+ when *require_pkcs
380
+ if params[:csr_path] != nil
381
+ params[:csr] = OpenSSL::X509::Request.new(File.read(params.fetch(:csr_path)))
382
+ elsif params[:csr_plain] != nil
383
+ params[:csr] = OpenSSL::X509::Request.new(params.fetch(:csr_plain))
384
+ end
385
+ check_csr(params[:csr])
386
+ else
387
+ fail ArgumentError, "No matching cases for initialize_certificates_and_csr"
388
+ end
389
+ params
390
+ rescue Exception => e
391
+ fail ArgumentError, "Parameter failed to initialize, check private key and cert path/plain"
392
+ end
393
+ end
394
+ end
395
+ end