mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-20 10:10:08 -08:00
use emersion/go-msgauth for DKIM (#2242)
Fixes #1041 (support ed25519-sha256 for DKIM)
This commit is contained in:
parent
9c3173f573
commit
68cee9e2cd
20 changed files with 1533 additions and 1504 deletions
199
vendor/github.com/emersion/go-msgauth/dkim/canonical.go
generated
vendored
Normal file
199
vendor/github.com/emersion/go-msgauth/dkim/canonical.go
generated
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
package dkim
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Canonicalization is a canonicalization algorithm.
|
||||
type Canonicalization string
|
||||
|
||||
const (
|
||||
CanonicalizationSimple Canonicalization = "simple"
|
||||
CanonicalizationRelaxed = "relaxed"
|
||||
)
|
||||
|
||||
type canonicalizer interface {
|
||||
CanonicalizeHeader(s string) string
|
||||
CanonicalizeBody(w io.Writer) io.WriteCloser
|
||||
}
|
||||
|
||||
var canonicalizers = map[Canonicalization]canonicalizer{
|
||||
CanonicalizationSimple: new(simpleCanonicalizer),
|
||||
CanonicalizationRelaxed: new(relaxedCanonicalizer),
|
||||
}
|
||||
|
||||
// crlfFixer fixes any lone LF without a preceding CR.
|
||||
type crlfFixer struct {
|
||||
cr bool
|
||||
}
|
||||
|
||||
func (cf *crlfFixer) Fix(b []byte) []byte {
|
||||
res := make([]byte, 0, len(b))
|
||||
for _, ch := range b {
|
||||
prevCR := cf.cr
|
||||
cf.cr = false
|
||||
switch ch {
|
||||
case '\r':
|
||||
cf.cr = true
|
||||
case '\n':
|
||||
if !prevCR {
|
||||
res = append(res, '\r')
|
||||
}
|
||||
}
|
||||
res = append(res, ch)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
type simpleCanonicalizer struct{}
|
||||
|
||||
func (c *simpleCanonicalizer) CanonicalizeHeader(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
type simpleBodyCanonicalizer struct {
|
||||
w io.Writer
|
||||
crlfBuf []byte
|
||||
crlfFixer crlfFixer
|
||||
}
|
||||
|
||||
func (c *simpleBodyCanonicalizer) Write(b []byte) (int, error) {
|
||||
written := len(b)
|
||||
b = append(c.crlfBuf, b...)
|
||||
|
||||
b = c.crlfFixer.Fix(b)
|
||||
|
||||
end := len(b)
|
||||
// If it ends with \r, maybe the next write will begin with \n
|
||||
if end > 0 && b[end-1] == '\r' {
|
||||
end--
|
||||
}
|
||||
// Keep all \r\n sequences
|
||||
for end >= 2 {
|
||||
prev := b[end-2]
|
||||
cur := b[end-1]
|
||||
if prev != '\r' || cur != '\n' {
|
||||
break
|
||||
}
|
||||
end -= 2
|
||||
}
|
||||
|
||||
c.crlfBuf = b[end:]
|
||||
|
||||
var err error
|
||||
if end > 0 {
|
||||
_, err = c.w.Write(b[:end])
|
||||
}
|
||||
return written, err
|
||||
}
|
||||
|
||||
func (c *simpleBodyCanonicalizer) Close() error {
|
||||
// Flush crlfBuf if it ends with a single \r (without a matching \n)
|
||||
if len(c.crlfBuf) > 0 && c.crlfBuf[len(c.crlfBuf)-1] == '\r' {
|
||||
if _, err := c.w.Write(c.crlfBuf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c.crlfBuf = nil
|
||||
|
||||
if _, err := c.w.Write([]byte(crlf)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *simpleCanonicalizer) CanonicalizeBody(w io.Writer) io.WriteCloser {
|
||||
return &simpleBodyCanonicalizer{w: w}
|
||||
}
|
||||
|
||||
type relaxedCanonicalizer struct{}
|
||||
|
||||
func (c *relaxedCanonicalizer) CanonicalizeHeader(s string) string {
|
||||
k, v, ok := strings.Cut(s, ":")
|
||||
if !ok {
|
||||
return strings.TrimSpace(strings.ToLower(s)) + ":" + crlf
|
||||
}
|
||||
|
||||
k = strings.TrimSpace(strings.ToLower(k))
|
||||
v = strings.Join(strings.FieldsFunc(v, func(r rune) bool {
|
||||
return r == ' ' || r == '\t' || r == '\n' || r == '\r'
|
||||
}), " ")
|
||||
return k + ":" + v + crlf
|
||||
}
|
||||
|
||||
type relaxedBodyCanonicalizer struct {
|
||||
w io.Writer
|
||||
crlfBuf []byte
|
||||
wsp bool
|
||||
written bool
|
||||
crlfFixer crlfFixer
|
||||
}
|
||||
|
||||
func (c *relaxedBodyCanonicalizer) Write(b []byte) (int, error) {
|
||||
written := len(b)
|
||||
|
||||
b = c.crlfFixer.Fix(b)
|
||||
|
||||
canonical := make([]byte, 0, len(b))
|
||||
for _, ch := range b {
|
||||
if ch == ' ' || ch == '\t' {
|
||||
c.wsp = true
|
||||
} else if ch == '\r' || ch == '\n' {
|
||||
c.wsp = false
|
||||
c.crlfBuf = append(c.crlfBuf, ch)
|
||||
} else {
|
||||
if len(c.crlfBuf) > 0 {
|
||||
canonical = append(canonical, c.crlfBuf...)
|
||||
c.crlfBuf = c.crlfBuf[:0]
|
||||
}
|
||||
if c.wsp {
|
||||
canonical = append(canonical, ' ')
|
||||
c.wsp = false
|
||||
}
|
||||
|
||||
canonical = append(canonical, ch)
|
||||
}
|
||||
}
|
||||
|
||||
if !c.written && len(canonical) > 0 {
|
||||
c.written = true
|
||||
}
|
||||
|
||||
_, err := c.w.Write(canonical)
|
||||
return written, err
|
||||
}
|
||||
|
||||
func (c *relaxedBodyCanonicalizer) Close() error {
|
||||
if c.written {
|
||||
if _, err := c.w.Write([]byte(crlf)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *relaxedCanonicalizer) CanonicalizeBody(w io.Writer) io.WriteCloser {
|
||||
return &relaxedBodyCanonicalizer{w: w}
|
||||
}
|
||||
|
||||
type limitedWriter struct {
|
||||
W io.Writer
|
||||
N int64
|
||||
}
|
||||
|
||||
func (w *limitedWriter) Write(b []byte) (int, error) {
|
||||
if w.N <= 0 {
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
skipped := 0
|
||||
if int64(len(b)) > w.N {
|
||||
b = b[:w.N]
|
||||
skipped = int(int64(len(b)) - w.N)
|
||||
}
|
||||
|
||||
n, err := w.W.Write(b)
|
||||
w.N -= int64(n)
|
||||
return n + skipped, err
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue