htlcswitch+invoices: always return incorrect_or_unknown_payment_details

In order to prevent information leaks by nodes probing with a payment
hash, this commit changes exit hop processing so that it always returns
incorrect_or_unknown_payment_details and leaves the prober in the dark
about whether an invoice actually exists.
This commit is contained in:
Joost Jager 2019-06-11 08:54:29 +02:00
parent 922f133fd2
commit 98fac9fb99
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
3 changed files with 14 additions and 71 deletions

@ -1204,30 +1204,16 @@ func (l *channelLink) processHodlEvent(hodlEvent invoices.HodlEvent,
)
}
} else {
l.debugf("Received hodl cancel event for %v, reason=%v",
hash, hodlEvent.CancelReason)
l.debugf("Received hodl cancel event for %v", hash)
hodlAction = func(htlc hodlHtlc) error {
var failure lnwire.FailureMessage
switch hodlEvent.CancelReason {
case invoices.CancelAmountTooLow:
fallthrough
case invoices.CancelInvoiceUnknown:
fallthrough
case invoices.CancelInvoiceCanceled:
failure = lnwire.NewFailIncorrectDetails(
// In case of a cancel, always return
// incorrect_or_unknown_payment_details in order to
// avoid leaking info.
failure := lnwire.NewFailIncorrectDetails(
htlc.pd.Amount,
)
case invoices.CancelExpiryTooSoon:
failure = &lnwire.FailFinalExpiryTooSoon{}
default:
return fmt.Errorf("unknown cancel reason: %v",
hodlEvent.CancelReason)
}
l.sendHTLCError(
htlc.pd.HtlcIndex, failure, htlc.obfuscator,
htlc.pd.SourceRef,

@ -1413,10 +1413,10 @@ func TestChannelLinkExpiryTooSoonExitNode(t *testing.T) {
}
switch ferr.FailureMessage.(type) {
case *lnwire.FailFinalExpiryTooSoon:
case *lnwire.FailIncorrectDetails:
default:
t.Fatalf("incorrect error, expected final time lock too "+
"early, instead have: %v", err)
t.Fatalf("expected incorrect_or_unknown_payment_details, "+
"instead have: %v", err)
}
}

@ -28,41 +28,6 @@ var (
DebugHash = DebugPre.Hash()
)
// HtlcCancelReason defines reasons for which htlcs can be canceled.
type HtlcCancelReason uint8
const (
// CancelInvoiceUnknown is returned if the preimage is unknown.
CancelInvoiceUnknown HtlcCancelReason = iota
// CancelExpiryTooSoon is returned when the timelock of the htlc
// does not satisfy the invoice cltv expiry requirement.
CancelExpiryTooSoon
// CancelInvoiceCanceled is returned when the invoice is already
// canceled and can't be paid to anymore.
CancelInvoiceCanceled
// CancelAmountTooLow is returned when the amount paid is too low.
CancelAmountTooLow
)
// String returns a human readable identifier for the cancel reason.
func (r HtlcCancelReason) String() string {
switch r {
case CancelInvoiceUnknown:
return "InvoiceUnknown"
case CancelExpiryTooSoon:
return "ExpiryTooSoon"
case CancelInvoiceCanceled:
return "InvoiceCanceled"
case CancelAmountTooLow:
return "CancelAmountTooLow"
default:
return "Unknown"
}
}
var (
// ErrInvoiceExpiryTooSoon is returned when an invoice is attempted to be
// accepted or settled with not enough blocks remaining.
@ -82,10 +47,6 @@ type HodlEvent struct {
// Hash is the htlc hash.
Hash lntypes.Hash
// CancelReason specifies the reason why invoice registry decided to
// cancel the htlc.
CancelReason HtlcCancelReason
}
// InvoiceRegistry is a central registry of all the outstanding invoices
@ -645,7 +606,6 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
return &HodlEvent{
Hash: rHash,
CancelReason: CancelInvoiceCanceled,
}, nil
// If invoice is already accepted, add this htlc to the list of
@ -662,7 +622,6 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
return &HodlEvent{
Hash: rHash,
CancelReason: CancelExpiryTooSoon,
}, nil
// If there are not enough blocks left, cancel the htlc.
@ -671,7 +630,6 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
return &HodlEvent{
Hash: rHash,
CancelReason: CancelAmountTooLow,
}, nil
// If this call settled the invoice, settle the htlc. Otherwise
@ -751,7 +709,6 @@ func (i *InvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error {
log.Debugf("Invoice(%v): canceled", payHash)
i.notifyHodlSubscribers(HodlEvent{
Hash: payHash,
CancelReason: CancelInvoiceCanceled,
})
i.notifyClients(payHash, invoice, channeldb.ContractCanceled)