poc verify
This commit is contained in:
155
dkim.go
155
dkim.go
@@ -17,6 +17,7 @@ import (
|
|||||||
//"net"
|
//"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -224,31 +225,56 @@ func Verify(email *[]byte) (VerifyOutput, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normalize
|
// Normalize
|
||||||
_, body, err := canonicalize(email, dkimHeader.MessageCanonicalization, dkimHeader.Headers)
|
headers, body, err := canonicalize(email, dkimHeader.MessageCanonicalization, dkimHeader.Headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PERMFAIL, err
|
return PERMFAIL, err
|
||||||
}
|
}
|
||||||
sigHash := strings.Split(dkimHeader.Algorithm, "-")
|
sigHash := strings.Split(dkimHeader.Algorithm, "-")
|
||||||
|
|
||||||
// expired ? TODO
|
// expired ?
|
||||||
|
if !dkimHeader.SignatureExpiration.IsZero() && dkimHeader.SignatureExpiration.Second() < time.Now().Second() {
|
||||||
|
return PERMFAIL, ErrVerifySignatureHasExpired
|
||||||
|
}
|
||||||
|
|
||||||
// get body hash
|
// get body hash
|
||||||
bodyHash, err := getBodyHash(&body, sigHash[0], dkimHeader.BodyLength)
|
bodyHash, err := getBodyHash(&body, sigHash[1], dkimHeader.BodyLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PERMFAIL, err
|
return PERMFAIL, err
|
||||||
}
|
}
|
||||||
println(bodyHash)
|
|
||||||
if bodyHash != dkimHeader.BodyHash {
|
if bodyHash != dkimHeader.BodyHash {
|
||||||
return PERMFAIL, ErrVerifyBodyHash
|
return PERMFAIL, ErrVerifyBodyHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// we do not set quesry method because if it's other validation failed earlier
|
// we do not set query method because if it's others, validation failed earlier
|
||||||
pubKey, verifyOutputOnError, err := newPubKeyFromDnsTxt(dkimHeader.Selector, dkimHeader.Domain)
|
pubKey, verifyOutputOnError, err := newPubKeyFromDnsTxt(dkimHeader.Selector, dkimHeader.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verifyOutputOnError, err
|
return verifyOutputOnError, err
|
||||||
}
|
}
|
||||||
println(pubKey)
|
|
||||||
|
|
||||||
|
// check if hash algo are compatible
|
||||||
|
compatible := false
|
||||||
|
for _, algo := range pubKey.HashAlgo {
|
||||||
|
if sigHash[1] == algo {
|
||||||
|
compatible = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !compatible {
|
||||||
|
return PERMFAIL, ErrVerifyInappropriateHashAlgo
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sig
|
||||||
|
dkimHeaderCano, err := canonicalizeHeader(dkimHeader.RawForSign, strings.Split(dkimHeader.MessageCanonicalization, "/")[0])
|
||||||
|
if err != nil {
|
||||||
|
return TEMPFAIL, err
|
||||||
|
}
|
||||||
|
toSignStr := string(headers) + dkimHeaderCano
|
||||||
|
toSign := bytes.TrimRight([]byte(toSignStr), " \r\n")
|
||||||
|
|
||||||
|
err = verifySignature(toSign, dkimHeader.SignatureData, &pubKey.PubKey, sigHash[1])
|
||||||
|
if err != nil {
|
||||||
|
return PERMFAIL, err
|
||||||
|
}
|
||||||
return SUCCESS, nil
|
return SUCCESS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,22 +283,13 @@ func canonicalize(email *[]byte, cano string, h []string) (headers, body []byte,
|
|||||||
body = []byte{}
|
body = []byte{}
|
||||||
rxReduceWS := regexp.MustCompile(`[ \t]+`)
|
rxReduceWS := regexp.MustCompile(`[ \t]+`)
|
||||||
|
|
||||||
// TODO: \n -> \r\n
|
rawHeaders, rawBody, err := getHeadersBody(email)
|
||||||
parts := bytes.SplitN(*email, []byte{13, 10, 13, 10}, 2)
|
|
||||||
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return headers, body, ErrBadMailFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty body
|
|
||||||
if len(parts[1]) == 0 {
|
|
||||||
parts[1] = []byte{13, 10}
|
|
||||||
}
|
|
||||||
|
|
||||||
canonicalizations := strings.Split(cano, "/")
|
canonicalizations := strings.Split(cano, "/")
|
||||||
|
|
||||||
// canonicalyze header
|
// canonicalyze header
|
||||||
headersList := list.New()
|
headersList, err := getHeadersList(&rawHeaders)
|
||||||
|
/*headersList := list.New()
|
||||||
currentHeader := []byte{}
|
currentHeader := []byte{}
|
||||||
for _, line := range bytes.SplitAfter(parts[0], []byte{10}) {
|
for _, line := range bytes.SplitAfter(parts[0], []byte{10}) {
|
||||||
if line[0] == 32 || line[0] == 9 {
|
if line[0] == 32 || line[0] == 9 {
|
||||||
@@ -289,7 +306,14 @@ func canonicalize(email *[]byte, cano string, h []string) (headers, body []byte,
|
|||||||
}
|
}
|
||||||
currentHeader = append(currentHeader, line...)
|
currentHeader = append(currentHeader, line...)
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// debug
|
||||||
|
/*fmt.Println("-------------------------------------------")
|
||||||
|
for e := headersList.Front(); e != nil; e = e.Next() {
|
||||||
|
fmt.Printf("|%s|\n", e.Value.(string))
|
||||||
}
|
}
|
||||||
|
fmt.Println("-------------------------------------------")*/
|
||||||
|
|
||||||
// pour chaque header a conserver on traverse tous les headers dispo
|
// pour chaque header a conserver on traverse tous les headers dispo
|
||||||
// If multi instance of a field we must keep it from the bottom to the top
|
// If multi instance of a field we must keep it from the bottom to the top
|
||||||
@@ -300,6 +324,7 @@ func canonicalize(email *[]byte, cano string, h []string) (headers, body []byte,
|
|||||||
match = nil
|
match = nil
|
||||||
headerToKeepToLower := strings.ToLower(headerToKeep)
|
headerToKeepToLower := strings.ToLower(headerToKeep)
|
||||||
for e := headersList.Front(); e != nil; e = e.Next() {
|
for e := headersList.Front(); e != nil; e = e.Next() {
|
||||||
|
//fmt.Printf("|%s|\n", e.Value.(string))
|
||||||
t := strings.Split(e.Value.(string), ":")
|
t := strings.Split(e.Value.(string), ":")
|
||||||
if strings.ToLower(t[0]) == headerToKeepToLower {
|
if strings.ToLower(t[0]) == headerToKeepToLower {
|
||||||
match = e
|
match = e
|
||||||
@@ -333,7 +358,7 @@ func canonicalize(email *[]byte, cano string, h []string) (headers, body []byte,
|
|||||||
// of the body to a single "CRLF".
|
// of the body to a single "CRLF".
|
||||||
// Note that a completely empty or missing body is canonicalized as a
|
// Note that a completely empty or missing body is canonicalized as a
|
||||||
// single "CRLF"; that is, the canonicalized length will be 2 octets.
|
// single "CRLF"; that is, the canonicalized length will be 2 octets.
|
||||||
body = bytes.TrimRight(parts[1], "\r\n")
|
body = bytes.TrimRight(rawBody, "\r\n")
|
||||||
body = append(body, []byte{13, 10}...)
|
body = append(body, []byte{13, 10}...)
|
||||||
} else {
|
} else {
|
||||||
// relaxed
|
// relaxed
|
||||||
@@ -346,8 +371,8 @@ func canonicalize(email *[]byte, cano string, h []string) (headers, body []byte,
|
|||||||
// does not end with a CRLF, a CRLF is added. (For email, this is
|
// does not end with a CRLF, a CRLF is added. (For email, this is
|
||||||
// only possible when using extensions to SMTP or non-SMTP transport
|
// only possible when using extensions to SMTP or non-SMTP transport
|
||||||
// mechanisms.)
|
// mechanisms.)
|
||||||
parts[1] = rxReduceWS.ReplaceAll(parts[1], []byte(" "))
|
rawBody = rxReduceWS.ReplaceAll(rawBody, []byte(" "))
|
||||||
for _, line := range bytes.SplitAfter(parts[1], []byte{10}) {
|
for _, line := range bytes.SplitAfter(rawBody, []byte{10}) {
|
||||||
line = bytes.TrimRight(line, " \r\n")
|
line = bytes.TrimRight(line, " \r\n")
|
||||||
|
|
||||||
if len(line) != 0 {
|
if len(line) != 0 {
|
||||||
@@ -427,6 +452,57 @@ func getBodyHash(body *[]byte, algo string, bodyLength uint) (string, error) {
|
|||||||
return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
|
return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*func getSignature(toSign *[]byte, key *rsa.PrivateKey, algo string) (string, error) {
|
||||||
|
var h1 hash.Hash
|
||||||
|
var h2 crypto.Hash
|
||||||
|
switch algo {
|
||||||
|
case "sha1":
|
||||||
|
h1 = sha1.New()
|
||||||
|
h2 = crypto.SHA1
|
||||||
|
break
|
||||||
|
case "sha256":
|
||||||
|
h1 = sha256.New()
|
||||||
|
h2 = crypto.SHA256
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return "", ErrVerifyInappropriateHashAlgo
|
||||||
|
}
|
||||||
|
|
||||||
|
// sign
|
||||||
|
h1.Write(*toSign)
|
||||||
|
sig, err := rsa.SignPKCS1v15(rand.Reader, key, h2, h1.Sum(nil))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(sig), nil
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
func verifySignature(toSign []byte, sig64 string, key *rsa.PublicKey, algo string) error {
|
||||||
|
var h1 hash.Hash
|
||||||
|
var h2 crypto.Hash
|
||||||
|
switch algo {
|
||||||
|
case "sha1":
|
||||||
|
h1 = sha1.New()
|
||||||
|
h2 = crypto.SHA1
|
||||||
|
break
|
||||||
|
case "sha256":
|
||||||
|
h1 = sha256.New()
|
||||||
|
h2 = crypto.SHA256
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return ErrVerifyInappropriateHashAlgo
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("|%s|", toSign)
|
||||||
|
h1.Write(toSign)
|
||||||
|
sig, err := base64.StdEncoding.DecodeString(sig64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rsa.VerifyPKCS1v15(key, h2, h1.Sum(nil), sig)
|
||||||
|
}
|
||||||
|
|
||||||
// removeFWS removes all FWS from string
|
// removeFWS removes all FWS from string
|
||||||
func removeFWS(in string) string {
|
func removeFWS(in string) string {
|
||||||
rxReduceWS := regexp.MustCompile(`[ \t]+`)
|
rxReduceWS := regexp.MustCompile(`[ \t]+`)
|
||||||
@@ -452,3 +528,40 @@ func validateCanonicalization(cano string) (string, error) {
|
|||||||
}
|
}
|
||||||
return cano, nil
|
return cano, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getHeadersList returns headers as list
|
||||||
|
func getHeadersList(rawHeader *[]byte) (*list.List, error) {
|
||||||
|
headersList := list.New()
|
||||||
|
currentHeader := []byte{}
|
||||||
|
for _, line := range bytes.SplitAfter(*rawHeader, []byte{10}) {
|
||||||
|
if line[0] == 32 || line[0] == 9 {
|
||||||
|
if len(currentHeader) == 0 {
|
||||||
|
return headersList, ErrBadMailFormatHeaders
|
||||||
|
}
|
||||||
|
currentHeader = append(currentHeader, line...)
|
||||||
|
} else {
|
||||||
|
// New header, save current if exists
|
||||||
|
if len(currentHeader) != 0 {
|
||||||
|
headersList.PushBack(string(currentHeader))
|
||||||
|
currentHeader = []byte{}
|
||||||
|
}
|
||||||
|
currentHeader = append(currentHeader, line...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headersList.PushBack(string(currentHeader))
|
||||||
|
return headersList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getHeadersBody return headers and body
|
||||||
|
func getHeadersBody(email *[]byte) ([]byte, []byte, error) {
|
||||||
|
// TODO: \n -> \r\n
|
||||||
|
parts := bytes.SplitN(*email, []byte{13, 10, 13, 10}, 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return []byte{}, []byte{}, ErrBadMailFormat
|
||||||
|
}
|
||||||
|
// Empty body
|
||||||
|
if len(parts[1]) == 0 {
|
||||||
|
parts[1] = []byte{13, 10}
|
||||||
|
}
|
||||||
|
return parts[0], parts[1], nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ type DkimHeader struct {
|
|||||||
// header with d = mail from domain)
|
// header with d = mail from domain)
|
||||||
//HeaderMailFromDomain string
|
//HeaderMailFromDomain string
|
||||||
|
|
||||||
// RawForsign represents the raw part (with non canonicalization) of the header
|
// RawForsign represents the raw part (without canonicalization) of the header
|
||||||
// used for computint sig in verify process
|
// used for computint sig in verify process
|
||||||
RawForSign string
|
RawForSign string
|
||||||
}
|
}
|
||||||
@@ -247,10 +247,30 @@ func NewFromEmail(email *[]byte) (*DkimHeader, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get raw dkim header
|
||||||
|
// we can't use m.header because header key will be converted with textproto.CanonicalMIMEHeaderKey
|
||||||
|
// ie if key in header is not DKIM-Signature but Dkim-Signature or DKIM-signature ot... other
|
||||||
|
// combination of case, verify will fail.
|
||||||
|
rawHeaders, _, err := getHeadersBody(email)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrBadMailFormat
|
||||||
|
}
|
||||||
|
rawHeadersList, err := getHeadersList(&rawHeaders)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dkHeaders := []string{}
|
||||||
|
for h := rawHeadersList.Front(); h != nil; h = h.Next() {
|
||||||
|
if strings.HasPrefix(strings.ToLower(h.Value.(string)), "dkim-signature") {
|
||||||
|
dkHeaders = append(dkHeaders, h.Value.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var keep *DkimHeader
|
var keep *DkimHeader
|
||||||
var keepErr error
|
var keepErr error
|
||||||
for _, dk := range m.Header[textproto.CanonicalMIMEHeaderKey("DKIM-Signature")] {
|
//for _, dk := range m.Header[textproto.CanonicalMIMEHeaderKey("DKIM-Signature")] {
|
||||||
parsed, err := parseDkHeader(dk)
|
for _, h := range dkHeaders {
|
||||||
|
parsed, err := parseDkHeader(h)
|
||||||
// if malformed dkim header try next
|
// if malformed dkim header try next
|
||||||
if err != nil {
|
if err != nil {
|
||||||
keepErr = err
|
keepErr = err
|
||||||
@@ -275,6 +295,8 @@ func NewFromEmail(email *[]byte) (*DkimHeader, error) {
|
|||||||
func parseDkHeader(header string) (dkh *DkimHeader, err error) {
|
func parseDkHeader(header string) (dkh *DkimHeader, err error) {
|
||||||
dkh = new(DkimHeader)
|
dkh = new(DkimHeader)
|
||||||
|
|
||||||
|
keyVal := strings.SplitN(header, ":", 2)
|
||||||
|
|
||||||
t := strings.LastIndex(header, "b=")
|
t := strings.LastIndex(header, "b=")
|
||||||
if t == -1 {
|
if t == -1 {
|
||||||
return nil, ErrDkimHeaderBTagNotFound
|
return nil, ErrDkimHeaderBTagNotFound
|
||||||
@@ -294,7 +316,7 @@ func parseDkHeader(header string) (dkh *DkimHeader, err error) {
|
|||||||
dkh.MessageCanonicalization = "simple/simple"
|
dkh.MessageCanonicalization = "simple/simple"
|
||||||
dkh.QueryMethods = []string{"dns/txt"}
|
dkh.QueryMethods = []string{"dns/txt"}
|
||||||
|
|
||||||
fs := strings.Split(header, ";")
|
fs := strings.Split(keyVal[1], ";")
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
flagData := strings.SplitN(f, "=", 2)
|
flagData := strings.SplitN(f, "=", 2)
|
||||||
flag := strings.ToLower(strings.TrimSpace(flagData[0]))
|
flag := strings.ToLower(strings.TrimSpace(flagData[0]))
|
||||||
@@ -313,7 +335,9 @@ func parseDkHeader(header string) (dkh *DkimHeader, err error) {
|
|||||||
}
|
}
|
||||||
mandatoryFlags["a"] = true
|
mandatoryFlags["a"] = true
|
||||||
case "b":
|
case "b":
|
||||||
dkh.SignatureData = removeFWS(data)
|
//dkh.SignatureData = removeFWS(data)
|
||||||
|
// remove all space
|
||||||
|
dkh.SignatureData = strings.Replace(removeFWS(data), " ", "", -1)
|
||||||
if len(dkh.SignatureData) != 0 {
|
if len(dkh.SignatureData) != 0 {
|
||||||
mandatoryFlags["b"] = true
|
mandatoryFlags["b"] = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,6 +252,8 @@ func Test_Sign(t *testing.T) {
|
|||||||
emailSimple := append([]byte(nil), email...)
|
emailSimple := append([]byte(nil), email...)
|
||||||
err = Sign(&emailSimple, options)
|
err = Sign(&emailSimple, options)
|
||||||
assert.Equal(t, []byte(signedSimpleSimple), emailSimple)
|
assert.Equal(t, []byte(signedSimpleSimple), emailSimple)
|
||||||
|
//fmt.Println(signedSimpleSimple)
|
||||||
|
//fmt.Println(string(emailSimple))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,4 +79,13 @@ var (
|
|||||||
|
|
||||||
// ErrVerifyBadKey when we can't parse pubkey
|
// ErrVerifyBadKey when we can't parse pubkey
|
||||||
ErrVerifyBadKey = errors.New("unable to parse pub key")
|
ErrVerifyBadKey = errors.New("unable to parse pub key")
|
||||||
|
|
||||||
|
// ErrVerifyNoKey when no key is found on DNS record
|
||||||
|
ErrVerifyNoKey = errors.New("no public key found in DNS TXT")
|
||||||
|
|
||||||
|
// ErrVerifySignatureHasExpired when signature has expired
|
||||||
|
ErrVerifySignatureHasExpired = errors.New("signature has expired")
|
||||||
|
|
||||||
|
// ErrVerifyInappropriateHashAlgo when h tag in pub key doesn't contain hash algo from a tag of DKIM header
|
||||||
|
ErrVerifyInappropriateHashAlgo = errors.New("inappropriate has algorithm")
|
||||||
)
|
)
|
||||||
|
|||||||
51
pubKeyRep.go
51
pubKeyRep.go
@@ -4,7 +4,6 @@ import (
|
|||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -40,6 +39,9 @@ func newPubKeyFromDnsTxt(selector, domain string) (*pubKeyRep, VerifyOutput, err
|
|||||||
pkr.Version = "DKIM1"
|
pkr.Version = "DKIM1"
|
||||||
pkr.HashAlgo = []string{"sha1", "sha256"}
|
pkr.HashAlgo = []string{"sha1", "sha256"}
|
||||||
pkr.KeyType = "rsa"
|
pkr.KeyType = "rsa"
|
||||||
|
pkr.ServiceType = []string{"all"}
|
||||||
|
pkr.FlagTesting = false
|
||||||
|
pkr.FlagIMustBeD = false
|
||||||
|
|
||||||
// parsing, we keep the first record
|
// parsing, we keep the first record
|
||||||
// TODO: if there is multiple record
|
// TODO: if there is multiple record
|
||||||
@@ -47,18 +49,22 @@ func newPubKeyFromDnsTxt(selector, domain string) (*pubKeyRep, VerifyOutput, err
|
|||||||
p := strings.Split(txt[0], ";")
|
p := strings.Split(txt[0], ";")
|
||||||
for i, data := range p {
|
for i, data := range p {
|
||||||
keyVal := strings.SplitN(data, "=", 2)
|
keyVal := strings.SplitN(data, "=", 2)
|
||||||
|
val := ""
|
||||||
|
if len(keyVal) > 1 {
|
||||||
|
val = strings.TrimSpace(keyVal[1])
|
||||||
|
}
|
||||||
switch strings.ToLower(strings.TrimSpace(keyVal[0])) {
|
switch strings.ToLower(strings.TrimSpace(keyVal[0])) {
|
||||||
case "v":
|
case "v":
|
||||||
// RFC: is this tag is specified it MUST be the first in the record
|
// RFC: is this tag is specified it MUST be the first in the record
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
return nil, PERMFAIL, ErrVerifyTagVMustBeTheFirst
|
return nil, PERMFAIL, ErrVerifyTagVMustBeTheFirst
|
||||||
}
|
}
|
||||||
pkr.Version = strings.TrimSpace(keyVal[1])
|
pkr.Version = val
|
||||||
if pkr.Version != "DKIM1" {
|
if pkr.Version != "DKIM1" {
|
||||||
return nil, PERMFAIL, ErrVerifyVersionMusBeDkim1
|
return nil, PERMFAIL, ErrVerifyVersionMusBeDkim1
|
||||||
}
|
}
|
||||||
case "h":
|
case "h":
|
||||||
p := strings.Split(strings.ToLower(keyVal[1]), ":")
|
p := strings.Split(strings.ToLower(val), ":")
|
||||||
pkr.HashAlgo = []string{}
|
pkr.HashAlgo = []string{}
|
||||||
for _, h := range p {
|
for _, h := range p {
|
||||||
h = strings.TrimSpace(h)
|
h = strings.TrimSpace(h)
|
||||||
@@ -71,34 +77,51 @@ func newPubKeyFromDnsTxt(selector, domain string) (*pubKeyRep, VerifyOutput, err
|
|||||||
pkr.HashAlgo = []string{"sha1", "sha256"}
|
pkr.HashAlgo = []string{"sha1", "sha256"}
|
||||||
}
|
}
|
||||||
case "k":
|
case "k":
|
||||||
if strings.ToLower(strings.TrimSpace(keyVal[1])) != "rsa" {
|
if strings.ToLower(val) != "rsa" {
|
||||||
return nil, PERMFAIL, ErrVerifyBadKeyType
|
return nil, PERMFAIL, ErrVerifyBadKeyType
|
||||||
}
|
}
|
||||||
case "n":
|
case "n":
|
||||||
pkr.Note = strings.TrimSpace(keyVal[1])
|
pkr.Note = val
|
||||||
case "p":
|
case "p":
|
||||||
rawkey := strings.TrimSpace(keyVal[1])
|
rawkey := val
|
||||||
if rawkey == "" {
|
if rawkey == "" {
|
||||||
return nil, PERMFAIL, ErrVerifyRevokedKey
|
return nil, PERMFAIL, ErrVerifyRevokedKey
|
||||||
}
|
}
|
||||||
// x509.ParsePKIXPublicKey(Dkim.PublicKey.PublicKey)
|
|
||||||
un64, err := base64.StdEncoding.DecodeString(rawkey)
|
un64, err := base64.StdEncoding.DecodeString(rawkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, PERMFAIL, ErrVerifyBadKey
|
return nil, PERMFAIL, ErrVerifyBadKey
|
||||||
}
|
}
|
||||||
pk, err := x509.ParsePKIXPublicKey(un64)
|
pk, err := x509.ParsePKIXPublicKey(un64)
|
||||||
pkr.PubKey = *pk.(*rsa.PublicKey)
|
pkr.PubKey = *pk.(*rsa.PublicKey)
|
||||||
// HERE
|
|
||||||
case "s":
|
case "s":
|
||||||
|
t := strings.Split(strings.ToLower(val), ":")
|
||||||
|
for _, tt := range t {
|
||||||
|
if tt == "*" {
|
||||||
|
pkr.ServiceType = []string{"all"}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if tt == "email" {
|
||||||
|
pkr.ServiceType = []string{"email"}
|
||||||
|
}
|
||||||
|
}
|
||||||
case "t":
|
case "t":
|
||||||
|
flags := strings.Split(strings.ToLower(val), ":")
|
||||||
|
for _, flag := range flags {
|
||||||
|
if flag == "y" {
|
||||||
|
pkr.FlagTesting = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if flag == "s" {
|
||||||
|
pkr.FlagIMustBeD = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: If no pubkey
|
// if no pubkey
|
||||||
|
if pkr.PubKey == (rsa.PublicKey{}) {
|
||||||
|
return nil, PERMFAIL, ErrVerifyNoKey
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println(txt, err)
|
return pkr, SUCCESS, nil
|
||||||
|
|
||||||
return nil, SUCCESS, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user