Sign: check & sanitize config

This commit is contained in:
Stéphane Depierrepont aka Toorop
2015-05-03 16:03:02 +02:00
parent a975eb7186
commit e6f591e5e3
3 changed files with 145 additions and 21 deletions

106
dkim.go
View File

@@ -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
}