Skip to content

Commit

Permalink
Merge pull request toorop#19 from terrabitz/Export-function-to-get-pa…
Browse files Browse the repository at this point in the history
…rsed-header

Expose and rename newDkimHeaderFromEmail
  • Loading branch information
toorop authored May 26, 2020
2 parents 897ad64 + 733d1a7 commit 76378ae
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 14 deletions.
4 changes: 2 additions & 2 deletions dkim.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func Sign(email *[]byte, options SigOptions) error {
// error: if an error occurs during verification
func Verify(email *[]byte, opts ...DNSOpt) (verifyOutput, error) {
// parse email
dkimHeader, err := newDkimHeaderFromEmail(email)
dkimHeader, err := GetHeader(email)
if err != nil {
if err == ErrDkimHeaderNotFound {
return NOTSIGNED, ErrDkimHeaderNotFound
Expand Down Expand Up @@ -254,7 +254,7 @@ func Verify(email *[]byte, opts ...DNSOpt) (verifyOutput, error) {
}

// compute sig
dkimHeaderCano, err := canonicalizeHeader(dkimHeader.RawForSign, strings.Split(dkimHeader.MessageCanonicalization, "/")[0])
dkimHeaderCano, err := canonicalizeHeader(dkimHeader.rawForSign, strings.Split(dkimHeader.MessageCanonicalization, "/")[0])
if err != nil {
return getVerifyOutput(TEMPFAIL, err, pubKey.FlagTesting)
}
Expand Down
24 changes: 12 additions & 12 deletions dkimHeader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"time"
)

type dkimHeader struct {
type DKIMHeader struct {
// Version This tag defines the version of DKIM
// specification that applies to the signature record.
// tag v
Expand Down Expand Up @@ -193,12 +193,12 @@ type dkimHeader struct {

// RawForsign represents the raw part (without canonicalization) of the header
// used for computint sig in verify process
RawForSign string
rawForSign string
}

// NewDkimHeaderBySigOptions return a new DkimHeader initioalized with sigOptions value
func newDkimHeaderBySigOptions(options SigOptions) *dkimHeader {
h := new(dkimHeader)
func newDkimHeaderBySigOptions(options SigOptions) *DKIMHeader {
h := new(DKIMHeader)
h.Version = "1"
h.Algorithm = options.Algo
h.MessageCanonicalization = options.Canonicalization
Expand All @@ -218,10 +218,10 @@ func newDkimHeaderBySigOptions(options SigOptions) *dkimHeader {
return h
}

// NewFromEmail return a new DkimHeader by parsing an email
// GetHeader return a new DKIMHeader by parsing an email
// Note: according to RFC 6376 an email can have multiple DKIM Header
// in this case we return the last inserted or the last with d== mail from
func newDkimHeaderFromEmail(email *[]byte) (*dkimHeader, error) {
func GetHeader(email *[]byte) (*DKIMHeader, error) {
m, err := mail.ReadMessage(bytes.NewReader(*email))
if err != nil {
return nil, err
Expand Down Expand Up @@ -265,7 +265,7 @@ func newDkimHeaderFromEmail(email *[]byte) (*dkimHeader, error) {
}
}

var keep *dkimHeader
var keep *DKIMHeader
var keepErr error
//for _, dk := range m.Header[textproto.CanonicalMIMEHeaderKey("DKIM-Signature")] {
for _, h := range dkHeaders {
Expand All @@ -291,19 +291,19 @@ func newDkimHeaderFromEmail(email *[]byte) (*dkimHeader, error) {
}

// parseDkHeader parse raw dkim header
func parseDkHeader(header string) (dkh *dkimHeader, err error) {
dkh = new(dkimHeader)
func parseDkHeader(header string) (dkh *DKIMHeader, err error) {
dkh = new(DKIMHeader)

keyVal := strings.SplitN(header, ":", 2)

t := strings.LastIndex(header, "b=")
if t == -1 {
return nil, ErrDkimHeaderBTagNotFound
}
dkh.RawForSign = header[0 : t+2]
dkh.rawForSign = header[0 : t+2]
p := strings.IndexByte(header[t:], ';')
if p != -1 {
dkh.RawForSign = dkh.RawForSign + header[t+p:]
dkh.rawForSign = dkh.rawForSign + header[t+p:]
}

// Mandatory
Expand Down Expand Up @@ -452,7 +452,7 @@ func parseDkHeader(header string) (dkh *dkimHeader, err error) {

// GetHeaderBase return base header for signers
// Todo: some refactoring needed...
func (d *dkimHeader) getHeaderBaseForSigning(bodyHash string) string {
func (d *DKIMHeader) getHeaderBaseForSigning(bodyHash string) string {
h := "DKIM-Signature: v=" + d.Version + "; a=" + d.Algorithm + "; q=" + strings.Join(d.QueryMethods, ":") + "; c=" + d.MessageCanonicalization + ";" + CRLF + TAB
subh := "s=" + d.Selector + ";"
if len(subh)+len(d.Domain)+4 > MaxHeaderLineLength {
Expand Down
54 changes: 54 additions & 0 deletions dkimHeader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package dkim

import (
"testing"

"github.com/go-test/deep"
)

func Test_GetHeader(t *testing.T) {
tests := []struct {
name string
input string
want *DKIMHeader
wantErr bool
}{
{
name: "Signed relaxed with length",
input: signedRelaxedRelaxedLength,
want: &DKIMHeader{
Version: "1",
Algorithm: "rsa-sha256",
QueryMethods: []string{"dns/txt"},
MessageCanonicalization: "relaxed/relaxed",
Selector: "test",
Domain: "tmail.io",
Auid: "@tmail.io",
BodyLength: 5,
Headers: []string{"from", "date", "mime-version", "received", "received"},
BodyHash: "GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=",
SignatureData: "byhiFWd0lAM1sqD1tl8S1DZtKNqgiEZp8jrGds6RRydnZkdX9rCPeL0Q5MYWBQ/JmQrml5" +
"pIghLwl/EshDBmNy65O6qO8pSSGgZmM3T7SRLMloex8bnrBJ4KSYcHV46639gVEWcBOKW0" +
"h1djZu2jaTuxGeJzlFVtw3Arf2B93cc=",
},
},
{
name: "No signature",
input: bodySimple,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
email := []byte(tt.input)
got, err := GetHeader(&email)
if (err != nil) != tt.wantErr {
t.Errorf("GetHeader() error = %v, wantErr %v", err, tt.wantErr)
return
}
if diff := deep.Equal(tt.want, got); diff != nil {
t.Error(diff)
}
})
}
}

0 comments on commit 76378ae

Please sign in to comment.