diff --git a/lib/email/dkim/signature.go b/lib/email/dkim/signature.go index c69a0519..acb3a73f 100644 --- a/lib/email/dkim/signature.go +++ b/lib/email/dkim/signature.go @@ -14,6 +14,7 @@ import ( "encoding/base64" "errors" "fmt" + "math" "strconv" "time" ) @@ -99,16 +100,20 @@ func Parse(value []byte) (sig *Signature, err error) { return nil, nil } - l := len(value) + var l = len(value) if value[l-2] != '\r' && value[l-1] != '\n' { return nil, errors.New("dkim: value must end with CRLF") } - p := newParser(value) + var ( + p = newParser(value) + + tag *tag + ) sig = &Signature{} for { - tag, err := p.fetchTag() + tag, err = p.fetchTag() if err != nil { return sig, err } @@ -454,7 +459,6 @@ func (sig *Signature) set(t *tag) (err error) { return errors.New("dkim: x=: " + err.Error()) } err = sig.validateTime() - case tagCanon: sig.CanonHeader, sig.CanonBody, err = unpackCanons(t.value) @@ -565,7 +569,14 @@ func (sig *Signature) validateTime() (err error) { if sig.ExpiredAt < sig.CreatedAt { return errCreatedTime } - + if sig.ExpiredAt > math.MaxInt64 { + // According to RFC 6376, + // "To avoid denial-of-service attacks, implementations MAY + // consider any value longer than 12 digits to be + // infinite.". + sig.ExpiredAt = math.MaxInt64 + return nil + } exp := time.Unix(int64(sig.ExpiredAt), 0) now := time.Now().Add(time.Hour * -1).Unix() if uint64(now) > sig.ExpiredAt { diff --git a/lib/email/dkim/signature_test.go b/lib/email/dkim/signature_test.go index ec02f7be..00157d33 100644 --- a/lib/email/dkim/signature_test.go +++ b/lib/email/dkim/signature_test.go @@ -189,6 +189,11 @@ func TestSignatureParse(t *testing.T) { "4bmp/YzhwvcubU4=;" + " c=simple/simple;" + " i=joe@football.example.com; q=dns/txt\r\n", + }, { + desc: `With expired-at more than 12 digits`, + in: "v=1; a=rsa-sha256; d=example.com; s=mykey; h=from; bh=bh; b=b; t=1117574938; x=9223372036854775808\r\n", + expRelaxed: "v=1; a=rsa-sha256; d=example.com; s=mykey; h=from; bh=bh; b=b; t=1117574938; x=9223372036854775807; \r\n", + expSimple: "v=1; a=rsa-sha256; d=example.com; s=mykey; h=from; bh=bh; b=b; t=1117574938; x=9223372036854775808\r\n", }} for _, c := range cases {