fix bug #5373: only allow existing payment redirection for contracts from the same merchant

This commit is contained in:
Florian Dold 2019-09-06 11:06:28 +02:00
parent 9297bbc825
commit f6c0108511
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
3 changed files with 36 additions and 11 deletions

View File

@ -733,10 +733,9 @@ export class Wallet {
return fu.href(); return fu.href();
} }
/** /**
* Check if a payment for the given taler://pay/ URI is possible. * Check if a payment for the given taler://pay/ URI is possible.
* *
* If the payment is possible, the signature are already generated but not * If the payment is possible, the signature are already generated but not
* yet send to the merchant. * yet send to the merchant.
*/ */
@ -769,6 +768,31 @@ export class Wallet {
console.log("proposal", proposal); console.log("proposal", proposal);
const differentPurchase = await this.q().getIndexed(
Stores.purchases.fulfillmentUrlIndex,
proposal.contractTerms.fulfillment_url,
);
if (differentPurchase) {
// We do this check to prevent merchant B to find out if we bought a
// digital product with merchant A by abusing the existing payment
// redirect feature.
if (
differentPurchase.contractTerms.merchant_pub !=
proposal.contractTerms.merchant_pub
) {
console.warn(
"merchant with different public key offered contract with same fulfillment URL as an existing purchase",
);
} else {
return {
status: "paid",
contractTerms: differentPurchase.contractTerms,
nextUrl: this.getNextUrl(differentPurchase.contractTerms),
};
}
}
// First check if we already payed for it. // First check if we already payed for it.
const purchase = await this.q().get( const purchase = await this.q().get(
Stores.purchases, Stores.purchases,
@ -779,7 +803,9 @@ export class Wallet {
const paymentAmount = Amounts.parseOrThrow(proposal.contractTerms.amount); const paymentAmount = Amounts.parseOrThrow(proposal.contractTerms.amount);
let wireFeeLimit; let wireFeeLimit;
if (proposal.contractTerms.max_wire_fee) { if (proposal.contractTerms.max_wire_fee) {
wireFeeLimit = Amounts.parseOrThrow(proposal.contractTerms.max_wire_fee); wireFeeLimit = Amounts.parseOrThrow(
proposal.contractTerms.max_wire_fee,
);
} else { } else {
wireFeeLimit = Amounts.getZero(paymentAmount.currency); wireFeeLimit = Amounts.getZero(paymentAmount.currency);
} }
@ -835,16 +861,12 @@ export class Wallet {
} }
if (uriResult.sessionId) { if (uriResult.sessionId) {
await this.submitPay( await this.submitPay(purchase.contractTermsHash, uriResult.sessionId);
purchase.contractTermsHash,
uriResult.sessionId,
);
} }
return { return {
status: "paid", status: "paid",
contractTerms: proposal.contractTerms, contractTerms: proposal.contractTerms,
proposalId: proposal.id!,
nextUrl: this.getNextUrl(purchase.contractTerms), nextUrl: this.getNextUrl(purchase.contractTerms),
}; };
} }
@ -1126,7 +1148,6 @@ export class Wallet {
return sp; return sp;
} }
private async sendReserveInfoToBank(reservePub: string) { private async sendReserveInfoToBank(reservePub: string) {
const reserve = await this.q().get<ReserveRecord>( const reserve = await this.q().get<ReserveRecord>(
Stores.reserves, Stores.reserves,

View File

@ -471,9 +471,9 @@ export interface PreparePayResultError {
error: string; error: string;
} }
export interface PreparePayResultPaid { export interface PreparePayResultPaid {
status: "paid"; status: "paid";
proposalId: number;
contractTerms: ContractTerms; contractTerms: ContractTerms;
nextUrl: string; nextUrl: string;
} }

View File

@ -92,10 +92,14 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }) {
); );
const doPayment = async () => { const doPayment = async () => {
if (payStatus.status !== "payment-possible") {
throw Error("invalid state");
}
const proposalId = payStatus.proposalId;
setNumTries(numTries + 1); setNumTries(numTries + 1);
try { try {
setLoading(true); setLoading(true);
const res = await wxApi.confirmPay(payStatus!.proposalId!, undefined); const res = await wxApi.confirmPay(proposalId, undefined);
document.location.href = res.nextUrl; document.location.href = res.nextUrl;
} catch (e) { } catch (e) {
console.error(e); console.error(e);