summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-03-26 23:44:27 +0100
committerAntoine A <>2024-03-26 23:44:27 +0100
commit00e8988a760d8e73225424185701c1f59508840a (patch)
tree2e26bd2089236fdec7ac626369eaf9edced0a952
parent3a0df963d964e5f1dc8c3105c4ad689525441408 (diff)
downloadlibeufin-00e8988a760d8e73225424185701c1f59508840a.tar.gz
libeufin-00e8988a760d8e73225424185701c1f59508840a.tar.bz2
libeufin-00e8988a760d8e73225424185701c1f59508840a.zip
Clean ebics setup code
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt63
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt72
2 files changed, 55 insertions, 80 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
index f9c83eba..a4870834 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
@@ -27,6 +27,7 @@ import io.ktor.client.plugins.*
import tech.libeufin.common.*
import tech.libeufin.common.crypto.*
import tech.libeufin.nexus.ebics.*
+import tech.libeufin.nexus.ebics.EbicsKeyMng.Order.*
import java.nio.file.*
import java.time.Instant
import kotlin.io.path.*
@@ -51,16 +52,6 @@ private fun loadOrGenerateClientKeys(path: Path): ClientPrivateKeysFile {
}
/**
- * Expresses the type of keying message that the user wants
- * to send to the bank.
- */
-enum class KeysOrderType {
- INI,
- HIA,
- HPB
-}
-
-/**
* @return the "this" string with a space every two characters.
*/
fun String.spaceEachTwo() =
@@ -107,36 +98,31 @@ suspend fun doKeysRequestAndUpdateState(
cfg: EbicsSetupConfig,
privs: ClientPrivateKeysFile,
client: HttpClient,
- orderType: KeysOrderType
+ order: EbicsKeyMng.Order
) {
- logger.info("Doing key request ${orderType.name}")
- val impl = EbicsKeyMng(cfg, privs, true)
- val req = when(orderType) {
- KeysOrderType.INI -> impl.INI()
- KeysOrderType.HIA -> impl.HIA()
- KeysOrderType.HPB -> impl.HPB()
- }
- val xml = client.postToBank(cfg.hostBaseUrl, req, "$orderType")
+ logger.info("Doing key request $order")
+ val req = EbicsKeyMng(cfg, privs, true).request(order)
+ val xml = client.postToBank(cfg.hostBaseUrl, req, order.name)
val resp = EbicsKeyMng.parseResponse(xml, privs.encryption_private_key)
- when (orderType) {
- KeysOrderType.INI, KeysOrderType.HIA -> {
+ when (order) {
+ INI, HIA -> {
if (resp.technicalCode == EbicsReturnCode.EBICS_INVALID_USER_OR_USER_STATE) {
- throw Exception("$orderType status code ${resp.technicalCode}: either your IDs are incorrect, or you already have keys registered with this bank")
+ throw Exception("$order status code ${resp.technicalCode}: either your IDs are incorrect, or you already have keys registered with this bank")
}
}
- KeysOrderType.HPB -> {
+ HPB -> {
if (resp.technicalCode == EbicsReturnCode.EBICS_AUTHENTICATION_FAILED) {
- throw Exception("$orderType status code ${resp.technicalCode}: could not download bank keys, send client keys (and/or related PDF document with --generate-registration-pdf) to the bank")
+ throw Exception("$order status code ${resp.technicalCode}: could not download bank keys, send client keys (and/or related PDF document with --generate-registration-pdf) to the bank")
}
}
}
- val orderData = resp.okOrFail("${orderType.name}")
- when (orderType) {
- KeysOrderType.INI -> privs.submitted_ini = true
- KeysOrderType.HIA -> privs.submitted_hia = true
- KeysOrderType.HPB -> {
+ val orderData = resp.okOrFail(order.name)
+ when (order) {
+ INI -> privs.submitted_ini = true
+ HIA -> privs.submitted_hia = true
+ HPB -> {
val orderData = requireNotNull(orderData) {
"HPB: missing order data"
}
@@ -149,15 +135,15 @@ suspend fun doKeysRequestAndUpdateState(
try {
persistBankKeys(bankKeys, cfg.bankPublicKeysFilename)
} catch (e: Exception) {
- throw Exception("Could not update the ${orderType.name} state on disk", e)
+ throw Exception("Could not update the $order state on disk", e)
}
}
}
- if (orderType != KeysOrderType.HPB) {
+ if (order != HPB) {
try {
persistClientKeys(privs, cfg.clientPrivateKeysFilename)
} catch (e: Exception) {
- throw Exception("Could not update the ${orderType.name} state on disk", e)
+ throw Exception("Could not update the $order state on disk", e)
}
}
@@ -214,7 +200,7 @@ class EbicsSetup: CliktCommand("Set up the EBICS subscriber") {
val cfg = extractEbicsConfig(common.config)
// Config is sane. Go (maybe) making the private keys.
val clientKeys = loadOrGenerateClientKeys(cfg.clientPrivateKeysFilename)
- val httpClient = HttpClient {
+ val client = HttpClient {
install(HttpTimeout) {
// It can take a lot of time for the bank to generate documents
socketTimeoutMillis = 5 * 60 * 1000
@@ -223,21 +209,16 @@ class EbicsSetup: CliktCommand("Set up the EBICS subscriber") {
// Privs exist. Upload their pubs
val keysNotSub = !clientKeys.submitted_ini
if ((!clientKeys.submitted_ini) || forceKeysResubmission)
- doKeysRequestAndUpdateState(cfg, clientKeys, httpClient, KeysOrderType.INI)
+ doKeysRequestAndUpdateState(cfg, clientKeys, client, INI)
// Eject PDF if the keys were submitted for the first time, or the user asked.
if (keysNotSub || generateRegistrationPdf) makePdf(clientKeys, cfg)
if ((!clientKeys.submitted_hia) || forceKeysResubmission)
- doKeysRequestAndUpdateState(cfg, clientKeys, httpClient, KeysOrderType.HIA)
+ doKeysRequestAndUpdateState(cfg, clientKeys, client, HIA)
// Checking if the bank keys exist on disk.
var bankKeys = loadBankKeys(cfg.bankPublicKeysFilename)
if (bankKeys == null) {
- doKeysRequestAndUpdateState(
- cfg,
- clientKeys,
- httpClient,
- KeysOrderType.HPB
- )
+ doKeysRequestAndUpdateState(cfg, clientKeys, client, HPB)
logger.info("Bank keys stored at ${cfg.bankPublicKeysFilename}")
bankKeys = loadBankKeys(cfg.bankPublicKeysFilename)!!
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt
index 48d10d18..02db79a0 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt
@@ -32,6 +32,7 @@ import java.time.ZoneId
import java.util.*
import javax.xml.datatype.DatatypeFactory
import java.security.interfaces.*
+import tech.libeufin.nexus.ebics.EbicsKeyMng.Order.*
/** EBICS protocol for key management */
class EbicsKeyMng(
@@ -40,45 +41,38 @@ class EbicsKeyMng(
private val ebics3: Boolean
) {
private val schema = if (ebics3) "H005" else "H004"
- fun INI(): ByteArray {
- val data = XMLOrderData(cfg, "SignaturePubKeyOrderData", "http://www.ebics.org/S00${if (ebics3) 2 else 1}") {
- el("SignaturePubKeyInfo") {
- RSAKeyXml(clientKeys.signature_private_key)
- el("SignatureVersion", "A006")
- }
- }
- return request("ebicsUnsecuredRequest", "INI", "0200", data)
+
+ enum class Order {
+ INI,
+ HIA,
+ HPB
}
- fun HIA(): ByteArray {
- val data = XMLOrderData(cfg, "HIARequestOrderData", "urn:org:ebics:$schema") {
- el("AuthenticationPubKeyInfo") {
- RSAKeyXml(clientKeys.authentication_private_key)
- el("AuthenticationVersion", "X002")
+ fun request(order: Order): ByteArray {
+ val (name, securityMedium, orderAttribute) = when (order) {
+ INI, HIA -> Triple("ebicsUnsecuredRequest", "0200", "DZNNN")
+ HPB -> Triple("ebicsNoPubKeyDigestsRequest", "0000", "DZHNN")
+ }
+ val data = when (order) {
+ INI -> XMLOrderData(cfg, "SignaturePubKeyOrderData", "http://www.ebics.org/S00${if (ebics3) 2 else 1}") {
+ el("SignaturePubKeyInfo") {
+ RSAKeyXml(clientKeys.signature_private_key)
+ el("SignatureVersion", "A006")
+ }
}
- el("EncryptionPubKeyInfo") {
- RSAKeyXml(clientKeys.encryption_private_key)
- el("EncryptionVersion", "E002")
+ HIA -> XMLOrderData(cfg, "HIARequestOrderData", "urn:org:ebics:$schema") {
+ el("AuthenticationPubKeyInfo") {
+ RSAKeyXml(clientKeys.authentication_private_key)
+ el("AuthenticationVersion", "X002")
+ }
+ el("EncryptionPubKeyInfo") {
+ RSAKeyXml(clientKeys.encryption_private_key)
+ el("EncryptionVersion", "E002")
+ }
}
+ HPB -> null
}
- return request("ebicsUnsecuredRequest", "HIA", "0200", data)
- }
-
- fun HPB(): ByteArray {
- val nonce = getNonce(128)
- return request("ebicsNoPubKeyDigestsRequest", "HPB", "0000", timestamp = Instant.now(), sign = true)
- }
-
- /* ----- Helpers ----- */
-
- private fun request(
- name: String,
- order: String,
- securityMedium: String,
- data: String? = null,
- timestamp: Instant? = null,
- sign: Boolean = false
- ): ByteArray {
+ val sign = order == HPB
val doc = XmlBuilder.toDom(name, "urn:org:ebics:$schema") {
attr("http://www.w3.org/2000/xmlns/", "xmlns", "urn:org:ebics:$schema")
attr("http://www.w3.org/2000/xmlns/", "xmlns:ds", "http://www.w3.org/2000/09/xmldsig#")
@@ -88,18 +82,18 @@ class EbicsKeyMng(
attr("authenticate", "true")
el("static") {
el("HostID", cfg.ebicsHostId)
- if (timestamp != null) {
+ if (order == HPB) {
el("Nonce", getNonce(128).encodeUpHex())
- el("Timestamp", timestamp.xmlDateTime())
+ el("Timestamp", Instant.now().xmlDateTime())
}
el("PartnerID", cfg.ebicsPartnerId)
el("UserID", cfg.ebicsUserId)
el("OrderDetails") {
if (ebics3) {
- el("AdminOrderType", order)
+ el("AdminOrderType", order.name)
} else {
- el("OrderType", order)
- el("OrderAttribute", if (order == "HPB") "DZHNN" else "DZNNN")
+ el("OrderType", order.name)
+ el("OrderAttribute", orderAttribute)
}
}
el("SecurityMedium", securityMedium)