1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package tls2021import (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"3132 "github.com/foxcpp/maddy/framework/config"33 "github.com/foxcpp/maddy/framework/module"34)3536type SelfSignedLoader struct {37 instName string38 serverNames []string3940 cert tls.Certificate41}4243func NewSelfSignedLoader(_, instName string, _, inlineArgs []string) (module.Module, error) {44 return &SelfSignedLoader{45 instName: instName,46 serverNames: inlineArgs,47 }, nil48}4950func (f *SelfSignedLoader) Init(cfg *config.Map) error {51 if _, err := cfg.Process(); err != nil {52 return err53 }5455 privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)56 if err != nil {57 return err58 }5960 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 err66 }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 }7576 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 err86 }8788 f.cert = tls.Certificate{89 Certificate: [][]byte{derBytes},90 PrivateKey: privKey,91 Leaf: cert,92 }93 return nil94}9596func (f *SelfSignedLoader) Name() string {97 return "tls.loader.self_signed"98}99100func (f *SelfSignedLoader) InstanceName() string {101 return f.instName102}103104func (f *SelfSignedLoader) ConfigureTLS(c *tls.Config) error {105 c.Certificates = []tls.Certificate{f.cert}106 return nil107}108109func init() {110 var _ module.TLSLoader = &SelfSignedLoader{}111 module.Register("tls.loader.self_signed", NewSelfSignedLoader)112}