libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit e6cb07cf62015f2aef5683192cf3841686839462
parent 4ea85ec6af7ebbe80427783cc6bcc1dae5a5a79c
Author: MS <ms@taler.net>
Date:   Wed, 29 Jul 2020 14:41:40 +0200

Sandbox error management.

Avoid passing private key inside exception objects,
but instead make the exception handler retrieve all
the needed information from the request context.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 15++++++---------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 18++++++++++++------
2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -26,6 +26,7 @@ import io.ktor.http.HttpStatusCode import io.ktor.request.receiveText import io.ktor.response.respond import io.ktor.response.respondText +import io.ktor.util.AttributeKey import org.apache.xml.security.binding.xmldsig.RSAKeyValueType import org.jetbrains.exposed.exceptions.ExposedSQLException import org.jetbrains.exposed.sql.* @@ -74,9 +75,7 @@ data class PainParseResult( open class EbicsRequestError( val errorText: String, - val errorCode: String, - // needed to sign the (error) response. - val hostAuthPriv: RSAPrivateCrtKey? = null + val errorCode: String ) : Exception("EBICS request error: $errorText ($errorCode)") class EbicsInvalidRequestError : EbicsRequestError( @@ -586,8 +585,7 @@ private fun handleCct(paymentRequest: String, initiatorName: String, ctx: Reques logger.warn("Could not insert new payment into the database: ${e}") throw EbicsRequestError( "[EBICS_PROCESSING_ERROR] ${e.sqlState}", - "091116", - ctx.hostAuthPriv + "091116" ) } } @@ -659,7 +657,6 @@ private suspend fun ApplicationCall.handleEbicsHia(header: EbicsUnsecuredRequest } } - private suspend fun ApplicationCall.handleEbicsIni(header: EbicsUnsecuredRequest.Header, orderData: ByteArray) { val plainOrderData = InflaterInputStream(orderData.inputStream()).use { it.readAllBytes() @@ -783,7 +780,6 @@ private fun ApplicationCall.ensureEbicsHost(requestHostID: String): EbicsHostPub } } - private suspend fun ApplicationCall.receiveEbicsXml(): Document { val body: String = receiveText() LOGGER.debug("Data received: $body") @@ -792,6 +788,8 @@ private suspend fun ApplicationCall.receiveEbicsXml(): Document { println("Problematic document was: $requestDocument") throw EbicsInvalidXmlError() } + val requestedHostID = requestDocument.getElementsByTagName("HostID") + this.attributes.put(AttributeKey("RequestedEbicsHostID"), requestedHostID.item(0).nodeValue) return requestDocument } @@ -1090,7 +1088,7 @@ private fun handleEbicsUploadTransactionTransmission(requestContext: RequestCont throw NotImplementedError() } } - +// req.header.static.hostID. private fun makeReqestContext(requestObject: EbicsRequest): RequestContext { val staticHeader = requestObject.header.static val requestedHostId = staticHeader.hostID @@ -1198,7 +1196,6 @@ suspend fun ApplicationCall.ebicsweb() { "ebicsRequest" -> { logger.debug("ebicsRequest ${XMLUtil.convertDomToString(requestDocument)}") val requestObject = requestDocument.toObject<EbicsRequest>() - val responseXmlStr = transaction { // Step 1 of 3: Get information about the host and subscriber val requestContext = makeReqestContext(requestObject) diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -61,6 +61,7 @@ import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.option +import io.ktor.util.AttributeKey import tech.libeufin.sandbox.PaymentsTable import tech.libeufin.sandbox.PaymentsTable.amount import tech.libeufin.sandbox.PaymentsTable.creditorBic @@ -181,7 +182,6 @@ fun serverMain(dbName: String) { } exception<EbicsRequestError> { cause -> - LOGGER.info("Client EBICS request was invalid") val resp = EbicsResponse.createForUploadWithError( cause.errorText, cause.errorCode, @@ -190,13 +190,19 @@ fun serverMain(dbName: String) { // already been caught by the chunking logic. EbicsTypes.TransactionPhaseType.TRANSFER ) - if (cause.hostAuthPriv == null) - throw SandboxError( - reason = "Cannot sign error response", - statusCode = HttpStatusCode.InternalServerError + + val hostAuthPriv = transaction { + val host = EbicsHostEntity.find { + EbicsHostsTable.hostID.upperCase() eq + call.attributes.get<String>(AttributeKey("EbicsHostID")).toUpperCase() + }.firstOrNull() ?: throw SandboxError( + HttpStatusCode.InternalServerError, + "Requested Ebics host ID not found." ) + CryptoUtil.loadRsaPrivateKey(host.authenticationPrivateKey.bytes) + } call.respondText( - XMLUtil.signEbicsResponse(resp, cause.hostAuthPriv), + XMLUtil.signEbicsResponse(resp, hostAuthPriv), ContentType.Application.Xml, HttpStatusCode.OK )