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 tls
 20
 21import (
 22	"crypto/ecdsa"
 23	"crypto/elliptic"
 24	"crypto/rand"
 25	"crypto/tls"
 26	"crypto/x509"
 27	"crypto/x509/pkix"
 28	"math/big"
 29	"net"
 30	"time"
 31
 32	"github.com/foxcpp/maddy/framework/config"
 33	"github.com/foxcpp/maddy/framework/module"
 34)
 35
 36type SelfSignedLoader struct {
 37	instName    string
 38	serverNames []string
 39
 40	cert tls.Certificate
 41}
 42
 43func NewSelfSignedLoader(_, instName string, _, inlineArgs []string) (module.Module, error) {
 44	return &SelfSignedLoader{
 45		instName:    instName,
 46		serverNames: inlineArgs,
 47	}, nil
 48}
 49
 50func (f *SelfSignedLoader) Init(cfg *config.Map) error {
 51	if _, err := cfg.Process(); err != nil {
 52		return err
 53	}
 54
 55	privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 56	if err != nil {
 57		return err
 58	}
 59
 60	notBefore := time.Now()
 61	notAfter := notBefore.Add(24 * time.Hour * 7)
 62	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
 63	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
 64	if err != nil {
 65		return err
 66	}
 67	cert := &x509.Certificate{
 68		SerialNumber: serialNumber,
 69		Subject:      pkix.Name{Organization: []string{"Maddy Self-Signed"}},
 70		NotBefore:    notBefore,
 71		NotAfter:     notAfter,
 72		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 73		ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 74	}
 75
 76	for _, name := range f.serverNames {
 77		if ip := net.ParseIP(name); ip != nil {
 78			cert.IPAddresses = append(cert.IPAddresses, ip)
 79		} else {
 80			cert.DNSNames = append(cert.DNSNames, name)
 81		}
 82	}
 83	derBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &privKey.PublicKey, privKey)
 84	if err != nil {
 85		return err
 86	}
 87
 88	f.cert = tls.Certificate{
 89		Certificate: [][]byte{derBytes},
 90		PrivateKey:  privKey,
 91		Leaf:        cert,
 92	}
 93	return nil
 94}
 95
 96func (f *SelfSignedLoader) Name() string {
 97	return "tls.loader.self_signed"
 98}
 99
100func (f *SelfSignedLoader) InstanceName() string {
101	return f.instName
102}
103
104func (f *SelfSignedLoader) ConfigureTLS(c *tls.Config) error {
105	c.Certificates = []tls.Certificate{f.cert}
106	return nil
107}
108
109func init() {
110	var _ module.TLSLoader = &SelfSignedLoader{}
111	module.Register("tls.loader.self_signed", NewSelfSignedLoader)
112}