mirror of
https://blitiri.com.ar/repos/chasquid
synced 2026-10-28 15:02:28 +00:00
61792e3bb4
Domains in addresses had very lax validation, which allowed them to include characters like "/". That could be exploited to trigger a daemon panic: a MAIL FROM "x@evil/foo" could be accepted and, on failed delivery, a DSN queued. Attempting to deliver the DSN would cause an MTA-STS cache lookup, which would panic because the domain includes a "/" and crash the server. Because the DSN would be queued, the server would crash again on restarts, and only self-recover after give_up_send_after (20h by default). To fix this, we now explicitly validate the domain when normalizing it, make MTA-STS cache not panic on invalid domains, and also make the SMTP courier fail permanently on invalid domains. Thanks to John JEAN <john@wargan.com> for finding and reporting this problem. The detailed report can be found in https://johnjean.io/advisories/chasquid-unauthenticated-remote-dos/.
69 lines
1.4 KiB
Go
69 lines
1.4 KiB
Go
// addtoqueue is a test helper which adds a queue item directly to the queue
|
|
// directory, behind chasquid's back.
|
|
//
|
|
// Note that chasquid does NOT support this, we do it before starting up the
|
|
// daemon for testing purposes only.
|
|
//
|
|
//go:build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
|
|
"blitiri.com.ar/go/chasquid/internal/queue"
|
|
)
|
|
|
|
var (
|
|
queueDir = flag.String("queue_dir", ".queue", "queue directory")
|
|
id = flag.String("id", "mid1234", "Message ID")
|
|
from = flag.String("from", "from", "Mail from")
|
|
rcpt = flag.String("rcpt", "rcpt", "Rcpt to")
|
|
rcptType = flag.String("rcpt_type", "EMAIL",
|
|
"Recipient type (EMAIL, PIPE, FORWARD)")
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
rType, ok := queue.Recipient_Type_value[*rcptType]
|
|
if !ok {
|
|
fmt.Printf("unknown recipient type %q\n", *rcptType)
|
|
os.Exit(1)
|
|
}
|
|
|
|
data, err := io.ReadAll(os.Stdin)
|
|
if err != nil {
|
|
fmt.Printf("error reading data: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
item := &queue.Item{
|
|
Message: queue.Message{
|
|
ID: *id,
|
|
From: *from,
|
|
To: []string{*rcpt},
|
|
Rcpt: []*queue.Recipient{
|
|
{
|
|
Address: *rcpt,
|
|
Type: queue.Recipient_Type(rType),
|
|
Status: queue.Recipient_PENDING,
|
|
},
|
|
},
|
|
Data: data,
|
|
},
|
|
CreatedAt: time.Now(),
|
|
}
|
|
|
|
os.MkdirAll(*queueDir, 0700)
|
|
err = item.WriteTo(*queueDir)
|
|
if err != nil {
|
|
fmt.Printf("error writing item: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|