maddy

Fork https://github.com/foxcpp/maddy

git clone git://git.lin.moe/go/maddy.git

  1/*
  2Maddy Mail Server - Composable all-in-one email server.
  3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
  4
  5This program is free software: you can redistribute it and/or modify
  6it under the terms of the GNU General Public License as published by
  7the Free Software Foundation, either version 3 of the License, or
  8(at your option) any later version.
  9
 10This program is distributed in the hope that it will be useful,
 11but WITHOUT ANY WARRANTY; without even the implied warranty of
 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13GNU General Public License for more details.
 14
 15You should have received a copy of the GNU General Public License
 16along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17*/
 18
 19package module
 20
 21import (
 22	"context"
 23	"crypto/tls"
 24)
 25
 26const (
 27	AuthDisabled     = "off"
 28	AuthMTASTS       = "mtasts"
 29	AuthDNSSEC       = "dnssec"
 30	AuthCommonDomain = "common_domain"
 31)
 32
 33type (
 34	TLSLevel int
 35	MXLevel  int
 36)
 37
 38const (
 39	TLSNone TLSLevel = iota
 40	TLSEncrypted
 41	TLSAuthenticated
 42)
 43
 44const (
 45	MXNone MXLevel = iota
 46	MX_MTASTS
 47	MX_DNSSEC
 48)
 49
 50func (l TLSLevel) String() string {
 51	switch l {
 52	case TLSNone:
 53		return "none"
 54	case TLSEncrypted:
 55		return "encrypted"
 56	case TLSAuthenticated:
 57		return "authenticated"
 58	}
 59	return "???"
 60}
 61
 62func (l MXLevel) String() string {
 63	switch l {
 64	case MXNone:
 65		return "none"
 66	case MX_MTASTS:
 67		return "mtasts"
 68	case MX_DNSSEC:
 69		return "dnssec"
 70	}
 71	return "???"
 72}
 73
 74type (
 75	// MXAuthPolicy is an object that provides security check for outbound connections.
 76	// It can do one of the following:
 77	//
 78	// - Check effective TLS level or MX level against some configured or
 79	// discovered value.
 80	// E.g. local policy.
 81	//
 82	// - Raise the security level if certain condition about used MX or
 83	// connection is met.
 84	// E.g. DANE MXAuthPolicy raises TLS level to Authenticated if a matching
 85	// TLSA record is discovered.
 86	//
 87	// - Reject the connection if certain condition about used MX or
 88	// connection is _not_ met.
 89	// E.g. An enforced MTA-STS MXAuthPolicy rejects MX records not matching it.
 90	//
 91	// It is not recommended to mix different types of behavior described above
 92	// in the same implementation.
 93	// Specifically, the first type is used mostly for local policies and is not
 94	// really practical.
 95	//
 96	// Modules implementing this interface should be registered with "mx_auth."
 97	// prefix in name.
 98	MXAuthPolicy interface {
 99		Start(*MsgMetadata) DeliveryMXAuthPolicy
100
101		// Weight is an integer in range 0-1000 that represents relative
102		// ordering of policy application.
103		Weight() int
104	}
105
106	// DeliveryMXAuthPolicy is an interface of per-delivery object that estabilishes
107	// and verifies required and effective security for MX records and TLS
108	// connections.
109	DeliveryMXAuthPolicy interface {
110		// PrepareDomain is called before DNS MX lookup and may asynchronously
111		// start additional lookups necessary for policy application in CheckMX
112		// or CheckConn.
113		//
114		// If there any errors - they should be deferred to the CheckMX or
115		// CheckConn call.
116		PrepareDomain(ctx context.Context, domain string)
117
118		// PrepareConn is called before connection and may asynchronously
119		// start additional lookups necessary for policy application in
120		// CheckConn.
121		//
122		// If there are any errors - they should be deferred to the CheckConn
123		// call.
124		PrepareConn(ctx context.Context, mx string)
125
126		// CheckMX is called to check whether the policy permits to use a MX.
127		//
128		// mxLevel contains the MX security level estabilished by checks
129		// executed before.
130		//
131		// domain is passed to the CheckMX to allow simpler implementation
132		// of stateless policy objects.
133		//
134		// dnssec is true if the MX lookup was performed using DNSSEC-enabled
135		// resolver and the zone is signed and its signature is valid.
136		CheckMX(ctx context.Context, mxLevel MXLevel, domain, mx string, dnssec bool) (MXLevel, error)
137
138		// CheckConn is called to check whether the policy permits to use this
139		// connection.
140		//
141		// tlsLevel and mxLevel contain the TLS security level estabilished by
142		// checks executed before.
143		//
144		// domain is passed to the CheckConn to allow simpler implementation
145		// of stateless policy objects.
146		//
147		// If tlsState.HandshakeCompleted is false, TLS is not used. If
148		// tlsState.VerifiedChains is nil, InsecureSkipVerify was used (no
149		// ServerName or PKI check was done).
150		CheckConn(ctx context.Context, mxLevel MXLevel, tlsLevel TLSLevel, domain, mx string, tlsState tls.ConnectionState) (TLSLevel, error)
151
152		// Reset cleans the internal object state for use with another message.
153		// newMsg may be nil if object is not needed anymore.
154		Reset(newMsg *MsgMetadata)
155	}
156)