blob: b9ff7b8d140ef4393048a41a54dca207295df0a0 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package dispatcher
import (
"bytes"
"errors"
"fmt"
"net/mail"
"strings"
)
const MaxEnvelopeBytes = 64 * 1024
// Envelope is the only application payload accepted by the dispatcher. Message
// must already be a complete YAMN transport envelope, not user supplied mail.
type Envelope struct {
EntryAddress string `json:"entry_address"`
Message []byte `json:"message"`
}
func (e Envelope) Validate(allowedDomains map[string]struct{}) error {
if len(e.Message) == 0 || len(e.Message) > MaxEnvelopeBytes {
return fmt.Errorf("invalid YAMN envelope size")
}
if bytes.Contains(e.Message, []byte("\r")) {
return errors.New("YAMN envelope must use LF line endings")
}
address, err := mail.ParseAddress(e.EntryAddress)
if err != nil || address.Address != e.EntryAddress {
return errors.New("invalid entry remailer address")
}
parts := strings.Split(address.Address, "@")
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return errors.New("invalid entry remailer address")
}
if _, ok := allowedDomains[strings.ToLower(parts[1])]; !ok {
return errors.New("entry remailer domain is not allowed")
}
if !bytes.HasPrefix(e.Message, []byte("To: "+e.EntryAddress+"\n")) {
return errors.New("YAMN envelope recipient does not match entry remailer")
}
if !bytes.Contains(e.Message, []byte("-----BEGIN REMAILER MESSAGE-----\n")) {
return errors.New("invalid YAMN envelope")
}
return nil
}
|