Extract several packages to form a public API

This commit is contained in:
fox.cpp 2020-07-14 20:36:18 +03:00
parent 7d497f88f0
commit bcceec4fe4
No known key found for this signature in database
GPG key ID: 5B991F6215D2FCC0
170 changed files with 385 additions and 392 deletions

View file

@ -1,163 +0,0 @@
package check
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/module"
)
// FailAction specifies actions that messages pipeline should take based on the
// result of the check.
//
// Its check module responsibility to apply FailAction on the CheckResult it
// returns. It is intended to be used as follows:
//
// Add the configuration directive to allow user to specify the action:
// cfg.Custom("SOME_action", false, false,
// func() (interface{}, error) {
// return check.FailAction{Quarantine: true}, nil
// }, check.FailActionDirective, &yourModule.SOMEAction)
// return in func literal is the default value, you might want to adjust it.
//
// Call yourModule.SOMEAction.Apply on CheckResult containing only the
// Reason field:
// func (yourModule YourModule) CheckConnection() module.CheckResult {
// return yourModule.SOMEAction.Apply(module.CheckResult{
// Reason: ...,
// })
// }
type FailAction struct {
Quarantine bool
Reject bool
ReasonOverride *exterrors.SMTPError
}
func FailActionDirective(m *config.Map, node config.Node) (interface{}, error) {
if len(node.Children) != 0 {
return nil, config.NodeErr(node, "can't declare block here")
}
val, err := ParseActionDirective(node.Args)
if err != nil {
return nil, config.NodeErr(node, "%v", err)
}
return val, nil
}
func ParseActionDirective(args []string) (FailAction, error) {
if len(args) == 0 {
return FailAction{}, errors.New("expected at least 1 argument")
}
res := FailAction{}
switch args[0] {
case "reject", "quarantine":
if len(args) > 1 {
var err error
res.ReasonOverride, err = ParseRejectDirective(args[1:])
if err != nil {
return FailAction{}, err
}
}
case "ignore":
default:
return FailAction{}, errors.New("invalid action")
}
res.Reject = args[0] == "reject"
res.Quarantine = args[0] == "quarantine"
return res, nil
}
// Apply merges the result of check execution with action configuration specified
// in the check configuration.
func (cfa FailAction) Apply(originalRes module.CheckResult) module.CheckResult {
if originalRes.Reason == nil {
return originalRes
}
if cfa.ReasonOverride != nil {
// Wrap instead of replace to preserve other fields.
originalRes.Reason = &exterrors.SMTPError{
Code: cfa.ReasonOverride.Code,
EnhancedCode: cfa.ReasonOverride.EnhancedCode,
Message: cfa.ReasonOverride.Message,
Err: originalRes.Reason,
}
}
originalRes.Quarantine = cfa.Quarantine || originalRes.Quarantine
originalRes.Reject = cfa.Reject || originalRes.Reject
return originalRes
}
func ParseRejectDirective(args []string) (*exterrors.SMTPError, error) {
code := 554
enchCode := exterrors.EnhancedCode{0, 7, 0}
msg := "Message rejected due to a local policy"
var err error
switch len(args) {
case 3:
msg = args[2]
if msg == "" {
return nil, fmt.Errorf("message can't be empty")
}
fallthrough
case 2:
enchCode, err = parseEnhancedCode(args[1])
if err != nil {
return nil, err
}
if enchCode[0] != 4 && enchCode[0] != 5 {
return nil, fmt.Errorf("enhanced code should use either 4 or 5 as a first number")
}
fallthrough
case 1:
code, err = strconv.Atoi(args[0])
if err != nil {
return nil, fmt.Errorf("invalid error code integer: %v", err)
}
if (code/100) != 4 && (code/100) != 5 {
return nil, fmt.Errorf("error code should start with either 4 or 5")
}
// If enchanced code is not set - set first digit based on provided "basic" code.
if enchCode[0] == 0 {
enchCode[0] = code / 100
}
case 0:
// If no codes provided at all - use 5.7.0 and 554.
enchCode[0] = 5
default:
return nil, fmt.Errorf("invalid count of arguments")
}
return &exterrors.SMTPError{
Code: code,
EnhancedCode: enchCode,
Message: msg,
Reason: "reject directive used",
}, nil
}
func parseEnhancedCode(s string) (exterrors.EnhancedCode, error) {
parts := strings.Split(s, ".")
if len(parts) != 3 {
return exterrors.EnhancedCode{}, fmt.Errorf("wrong amount of enhanced code parts")
}
code := exterrors.EnhancedCode{}
for i, part := range parts {
num, err := strconv.Atoi(part)
if err != nil {
return code, err
}
code[i] = num
}
return code, nil
}

View file

@ -16,12 +16,12 @@ import (
"strings"
"github.com/emersion/go-message/textproto"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
)
@ -43,7 +43,7 @@ type Check struct {
log log.Logger
stage Stage
actions map[int]check.FailAction
actions map[int]modconfig.FailAction
cmd string
cmdArgs []string
}
@ -51,11 +51,11 @@ type Check struct {
func New(modName, instName string, aliases, inlineArgs []string) (module.Module, error) {
c := &Check{
instName: instName,
actions: map[int]check.FailAction{
1: check.FailAction{
actions: map[int]modconfig.FailAction{
1: modconfig.FailAction{
Reject: true,
},
2: check.FailAction{
2: modconfig.FailAction{
Quarantine: true,
},
},
@ -105,7 +105,7 @@ func (c *Check) Init(cfg *config.Map) error {
if err != nil {
return config.NodeErr(node, "%v", err)
}
action, err := check.ParseActionDirective(node.Args[1:])
action, err := modconfig.ParseActionDirective(node.Args[1:])
if err != nil {
return config.NodeErr(node, "%v", err)
}

View file

@ -12,13 +12,13 @@ import (
"github.com/emersion/go-message/textproto"
"github.com/emersion/go-msgauth/authres"
"github.com/emersion/go-msgauth/dkim"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/dns"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/dns"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
)
@ -28,8 +28,8 @@ type Check struct {
requiredFields map[string]struct{}
allowBodySubset bool
brokenSigAction check.FailAction
noSigAction check.FailAction
brokenSigAction modconfig.FailAction
noSigAction modconfig.FailAction
failOpen bool
resolver dns.Resolver
@ -55,12 +55,12 @@ func (c *Check) Init(cfg *config.Map) error {
cfg.Bool("fail_open", false, false, &c.failOpen)
cfg.Custom("broken_sig_action", false, false,
func() (interface{}, error) {
return check.FailAction{}, nil
}, check.FailActionDirective, &c.brokenSigAction)
return modconfig.FailAction{}, nil
}, modconfig.FailActionDirective, &c.brokenSigAction)
cfg.Custom("no_sig_action", false, false,
func() (interface{}, error) {
return check.FailAction{}, nil
}, check.FailActionDirective, &c.noSigAction)
return modconfig.FailAction{}, nil
}, modconfig.FailActionDirective, &c.noSigAction)
_, err := cfg.Process()
if err != nil {
return err

View file

@ -8,10 +8,10 @@ import (
"github.com/emersion/go-msgauth/authres"
"github.com/foxcpp/go-mockdns"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/testutils"
)

View file

@ -4,11 +4,12 @@ import (
"net"
"strings"
"github.com/foxcpp/maddy/internal/address"
"github.com/foxcpp/maddy/framework/address"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/dns"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/dns"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/module"
)
func requireMatchingRDNS(ctx check.StatelessCheckContext) module.CheckResult {
@ -217,10 +218,10 @@ func requireMatchingEHLO(ctx check.StatelessCheckContext) module.CheckResult {
}
func init() {
check.RegisterStatelessCheck("require_matching_rdns", check.FailAction{Quarantine: true},
check.RegisterStatelessCheck("require_matching_rdns", modconfig.FailAction{Quarantine: true},
requireMatchingRDNS, nil, nil, nil)
check.RegisterStatelessCheck("require_mx_record", check.FailAction{Quarantine: true},
check.RegisterStatelessCheck("require_mx_record", modconfig.FailAction{Quarantine: true},
nil, requireMXRecord, nil, nil)
check.RegisterStatelessCheck("require_matching_ehlo", check.FailAction{Quarantine: true},
check.RegisterStatelessCheck("require_matching_ehlo", modconfig.FailAction{Quarantine: true},
requireMatchingEHLO, nil, nil, nil)
}

View file

@ -6,9 +6,9 @@ import (
"github.com/emersion/go-smtp"
"github.com/foxcpp/go-mockdns"
"github.com/foxcpp/maddy/framework/future"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/future"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/internal/testutils"
)

View file

@ -6,8 +6,8 @@ import (
"strconv"
"strings"
"github.com/foxcpp/maddy/internal/dns"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/framework/dns"
"github.com/foxcpp/maddy/framework/exterrors"
)
type ListedErr struct {

View file

@ -10,13 +10,13 @@ import (
"github.com/emersion/go-message/textproto"
"github.com/emersion/go-smtp"
"github.com/foxcpp/maddy/internal/address"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/dns"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/address"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
"github.com/foxcpp/maddy/framework/dns"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
"golang.org/x/sync/errgroup"
)

View file

@ -10,11 +10,11 @@ import (
"github.com/emersion/go-message/textproto"
"github.com/emersion/go-milter"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
)

View file

@ -1,9 +1,10 @@
package requiretls
import (
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/module"
)
func requireTLS(ctx check.StatelessCheckContext) module.CheckResult {
@ -22,5 +23,5 @@ func requireTLS(ctx check.StatelessCheckContext) module.CheckResult {
}
func init() {
check.RegisterStatelessCheck("require_tls", check.FailAction{Reject: true}, requireTLS, nil, nil, nil)
check.RegisterStatelessCheck("require_tls", modconfig.FailAction{Reject: true}, requireTLS, nil, nil, nil)
}

View file

@ -11,12 +11,12 @@ import (
"strings"
"github.com/emersion/go-message/textproto"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
)
@ -32,10 +32,10 @@ type Check struct {
tag string
mtaName string
ioErrAction check.FailAction
errorRespAction check.FailAction
addHdrAction check.FailAction
rewriteSubjAction check.FailAction
ioErrAction modconfig.FailAction
errorRespAction modconfig.FailAction
addHdrAction modconfig.FailAction
rewriteSubjAction modconfig.FailAction
client *http.Client
}
@ -81,20 +81,20 @@ func (c *Check) Init(cfg *config.Map) error {
cfg.String("hostname", true, false, "", &c.mtaName)
cfg.Custom("io_error_action", false, false,
func() (interface{}, error) {
return check.FailAction{}, nil
}, check.FailActionDirective, &c.ioErrAction)
return modconfig.FailAction{}, nil
}, modconfig.FailActionDirective, &c.ioErrAction)
cfg.Custom("error_resp_action", false, false,
func() (interface{}, error) {
return check.FailAction{}, nil
}, check.FailActionDirective, &c.errorRespAction)
return modconfig.FailAction{}, nil
}, modconfig.FailActionDirective, &c.errorRespAction)
cfg.Custom("add_header_action", false, false,
func() (interface{}, error) {
return check.FailAction{Quarantine: true}, nil
}, check.FailActionDirective, &c.addHdrAction)
return modconfig.FailAction{Quarantine: true}, nil
}, modconfig.FailActionDirective, &c.addHdrAction)
cfg.Custom("rewrite_subj_action", false, false,
func() (interface{}, error) {
return check.FailAction{Quarantine: true}, nil
}, check.FailActionDirective, &c.rewriteSubjAction)
return modconfig.FailAction{Quarantine: true}, nil
}, modconfig.FailActionDirective, &c.rewriteSubjAction)
cfg.StringList("flags", false, false, []string{"pass_all"}, &flags)
if _, err := cfg.Process(); err != nil {
return err

View file

@ -9,10 +9,10 @@ package directory_name_here
import (
"github.com/emersion/go-message/textproto"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
)

View file

@ -12,15 +12,15 @@ import (
"github.com/emersion/go-message/textproto"
"github.com/emersion/go-msgauth/authres"
"github.com/emersion/go-msgauth/dmarc"
"github.com/foxcpp/maddy/internal/address"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/check"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/framework/address"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/dns"
"github.com/foxcpp/maddy/framework/exterrors"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
maddydmarc "github.com/foxcpp/maddy/internal/dmarc"
"github.com/foxcpp/maddy/internal/dns"
"github.com/foxcpp/maddy/internal/exterrors"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/internal/target"
"golang.org/x/net/idna"
)
@ -31,12 +31,12 @@ type Check struct {
instName string
enforceEarly bool
noneAction check.FailAction
neutralAction check.FailAction
failAction check.FailAction
softfailAction check.FailAction
permerrAction check.FailAction
temperrAction check.FailAction
noneAction modconfig.FailAction
neutralAction modconfig.FailAction
failAction modconfig.FailAction
softfailAction modconfig.FailAction
permerrAction modconfig.FailAction
temperrAction modconfig.FailAction
log log.Logger
}
@ -61,28 +61,28 @@ func (c *Check) Init(cfg *config.Map) error {
cfg.Bool("enforce_early", true, false, &c.enforceEarly)
cfg.Custom("none_action", false, false,
func() (interface{}, error) {
return check.FailAction{}, nil
}, check.FailActionDirective, &c.noneAction)
return modconfig.FailAction{}, nil
}, modconfig.FailActionDirective, &c.noneAction)
cfg.Custom("neutral_action", false, false,
func() (interface{}, error) {
return check.FailAction{}, nil
}, check.FailActionDirective, &c.neutralAction)
return modconfig.FailAction{}, nil
}, modconfig.FailActionDirective, &c.neutralAction)
cfg.Custom("fail_action", false, false,
func() (interface{}, error) {
return check.FailAction{Quarantine: true}, nil
}, check.FailActionDirective, &c.failAction)
return modconfig.FailAction{Quarantine: true}, nil
}, modconfig.FailActionDirective, &c.failAction)
cfg.Custom("softfail_action", false, false,
func() (interface{}, error) {
return check.FailAction{Quarantine: true}, nil
}, check.FailActionDirective, &c.softfailAction)
return modconfig.FailAction{Quarantine: true}, nil
}, modconfig.FailActionDirective, &c.softfailAction)
cfg.Custom("permerr_action", false, false,
func() (interface{}, error) {
return check.FailAction{Reject: true}, nil
}, check.FailActionDirective, &c.permerrAction)
return modconfig.FailAction{Reject: true}, nil
}, modconfig.FailActionDirective, &c.permerrAction)
cfg.Custom("temperr_action", false, false,
func() (interface{}, error) {
return check.FailAction{Reject: true}, nil
}, check.FailActionDirective, &c.temperrAction)
return modconfig.FailAction{Reject: true}, nil
}, modconfig.FailActionDirective, &c.temperrAction)
_, err := cfg.Process()
if err != nil {
return err

View file

@ -6,11 +6,12 @@ import (
"runtime/trace"
"github.com/emersion/go-message/textproto"
"github.com/foxcpp/maddy/internal/buffer"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/dns"
"github.com/foxcpp/maddy/internal/log"
"github.com/foxcpp/maddy/internal/module"
"github.com/foxcpp/maddy/framework/buffer"
"github.com/foxcpp/maddy/framework/config"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/dns"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
"github.com/foxcpp/maddy/internal/target"
)
@ -43,9 +44,9 @@ type statelessCheck struct {
logger log.Logger
// One used by Init if config option is not passed by a user.
defaultFailAction FailAction
defaultFailAction modconfig.FailAction
// The actual fail action that should be applied.
failAction FailAction
failAction modconfig.FailAction
connCheck FuncConnCheck
senderCheck FuncSenderCheck
@ -138,7 +139,7 @@ func (c *statelessCheck) Init(cfg *config.Map) error {
cfg.Custom("fail_action", false, false,
func() (interface{}, error) {
return c.defaultFailAction, nil
}, FailActionDirective, &c.failAction)
}, modconfig.FailActionDirective, &c.failAction)
_, err := cfg.Process()
return err
}
@ -161,7 +162,7 @@ func (c *statelessCheck) InstanceName() string {
// StatelessCheck supports different action types based on the user configuration, but the particular check
// code doesn't need to know about it. It should assume that it is always "Reject" and hence it should
// populate Reason field of the result object with the relevant error description.
func RegisterStatelessCheck(name string, defaultFailAction FailAction, connCheck FuncConnCheck, senderCheck FuncSenderCheck, rcptCheck FuncRcptCheck, bodyCheck FuncBodyCheck) {
func RegisterStatelessCheck(name string, defaultFailAction modconfig.FailAction, connCheck FuncConnCheck, senderCheck FuncSenderCheck, rcptCheck FuncRcptCheck, bodyCheck FuncBodyCheck) {
module.Register(name, func(modName, instName string, aliases, inlineArgs []string) (module.Module, error) {
if len(inlineArgs) != 0 {
return nil, fmt.Errorf("%s: inline arguments are not used", modName)