Sign: check & sanitize config
This commit is contained in:
106
dkim.go
106
dkim.go
@@ -2,38 +2,118 @@ package dkim
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// sigOptions represents signing options
|
||||
type sigOptions struct {
|
||||
PrivateKey string
|
||||
Domain string
|
||||
Selector string
|
||||
Auid string
|
||||
|
||||
// DKIM version (default 1)
|
||||
Version uint
|
||||
|
||||
// Private key used for signing (required)
|
||||
PrivateKey string
|
||||
|
||||
// Domain (required)
|
||||
Domain string
|
||||
|
||||
// Selector (required)
|
||||
Selector string
|
||||
|
||||
// The Agent of User IDentifier
|
||||
Auid string
|
||||
|
||||
// Message canonicalization (plain-text; OPTIONAL, default is
|
||||
// "simple/simple"). This tag informs the Verifier of the type of
|
||||
// canonicalization used to prepare the message for signing.
|
||||
Canonicalization string
|
||||
Algo string
|
||||
Headers []string
|
||||
Timestamp time.Time
|
||||
Expiration time.Time
|
||||
|
||||
// The algorithm used to generate the signature
|
||||
//"rsa-sha1" or "rsa-sha256"
|
||||
Algo string
|
||||
|
||||
// Signed header fields
|
||||
Headers []string
|
||||
|
||||
// Body length count( if set to 0 this tag is ommited in Dkim header)
|
||||
BodyLength uint
|
||||
|
||||
// Query Methods used to retrieve the public key
|
||||
QueryMethods []string
|
||||
|
||||
// Add a signature timestamp
|
||||
AddSignatureTimestamp bool
|
||||
|
||||
// Time validity of the signature (0=never)
|
||||
SignatureExpireIn time.Duration
|
||||
}
|
||||
|
||||
// NewSigOption returns new sigoption with some defaults value
|
||||
func NewSigOptions() sigOptions {
|
||||
return sigOptions{
|
||||
Canonicalization: "simple/simple",
|
||||
Algo: "rsa-sha256",
|
||||
Version: 1,
|
||||
Canonicalization: "simple/simple",
|
||||
Algo: "rsa-sha256",
|
||||
Headers: []string{"from"},
|
||||
BodyLength: 0,
|
||||
QueryMethods: []string{"dns/txt"},
|
||||
AddSignatureTimestamp: false,
|
||||
SignatureExpireIn: 0 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// Sign signs an email
|
||||
func Sign(email *bytes.Reader, options sigOptions) (*bytes.Reader, error) {
|
||||
// check config
|
||||
// check && sanitize config
|
||||
|
||||
// private key (not empty & TODO: valid)
|
||||
// PrivateKey (required & TODO: valid)
|
||||
if options.PrivateKey == "" {
|
||||
return nil, ErrConfigNoPrivateKey
|
||||
return nil, ErrSignPrivateKeyRequired
|
||||
}
|
||||
|
||||
// Domain required
|
||||
if options.Domain == "" {
|
||||
return nil, ErrSignDomainRequired
|
||||
}
|
||||
|
||||
// Selector required
|
||||
if options.Selector == "" {
|
||||
return nil, ErrSignSelectorRequired
|
||||
}
|
||||
|
||||
// Canonicalization
|
||||
options.Canonicalization = strings.ToLower(options.Canonicalization)
|
||||
p := strings.Split(options.Canonicalization, "/")
|
||||
if len(p) > 2 {
|
||||
return nil, ErrSignBadCanonicalization
|
||||
}
|
||||
for _, c := range p {
|
||||
if c != "simple" && c != "relaxed" {
|
||||
return nil, ErrSignBadCanonicalization
|
||||
}
|
||||
}
|
||||
|
||||
// Algo
|
||||
options.Algo = strings.ToLower(options.Algo)
|
||||
if options.Algo != "rsa-sha1" && options.Algo != "rsa-sha256" {
|
||||
return nil, ErrSignBadAlgo
|
||||
}
|
||||
|
||||
// Header must contain "from"
|
||||
// normalize -> strtlower
|
||||
hasFrom := false
|
||||
for i, h := range options.Headers {
|
||||
options.Headers[i] = strings.ToLower(h)
|
||||
if h == "from" {
|
||||
hasFrom = true
|
||||
}
|
||||
}
|
||||
if !hasFrom {
|
||||
return nil, ErrSignHeaderShouldContainsFrom
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user