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/tls"2324 "github.com/foxcpp/maddy/framework/config"25 modconfig "github.com/foxcpp/maddy/framework/config/module"26 "github.com/foxcpp/maddy/framework/log"27 "github.com/foxcpp/maddy/framework/module"28)2930type TLSConfig struct {31 loader module.TLSLoader32 baseCfg *tls.Config33}3435func (cfg *TLSConfig) Get() (*tls.Config, error) {36 if cfg.loader == nil {37 return nil, nil38 }39 tlsCfg := cfg.baseCfg.Clone()4041 err := cfg.loader.ConfigureTLS(tlsCfg)42 if err != nil {43 return nil, err44 }4546 return tlsCfg, nil47}4849// TLSDirective reads the TLS configuration and adds the reload handler to50// reread certificates on SIGUSR2.51//52// The returned value is *tls.Config with GetConfigForClient set.53// If the 'tls off' is used, returned value is nil.54func TLSDirective(m *config.Map, node config.Node) (interface{}, error) {55 cfg, err := readTLSBlock(m.Globals, node)56 if err != nil {57 return nil, err58 }5960 if cfg == nil {61 return nil, nil62 }6364 return &tls.Config{65 GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) {66 return cfg.Get()67 },68 }, nil69}7071func readTLSBlock(globals map[string]interface{}, blockNode config.Node) (*TLSConfig, error) {72 baseCfg := tls.Config{73 // Workaround for issue https://github.com/foxcpp/maddy/issues/73074 SessionTicketsDisabled: true,75 }7677 var loader module.TLSLoader78 if len(blockNode.Args) > 0 {79 if blockNode.Args[0] == "off" {80 return nil, nil81 }8283 err := modconfig.ModuleFromNode("tls.loader", blockNode.Args, config.Node{}, globals, &loader)84 if err != nil {85 return nil, err86 }87 }8889 childM := config.NewMap(globals, blockNode)90 var tlsVersions [2]uint169192 childM.Custom("loader", false, false, func() (interface{}, error) {93 return loader, nil94 }, func(_ *config.Map, node config.Node) (interface{}, error) {95 var l module.TLSLoader96 err := modconfig.ModuleFromNode("tls.loader", node.Args, node, globals, &l)97 return l, err98 }, &loader)99100 childM.Custom("protocols", false, false, func() (interface{}, error) {101 return [2]uint16{tls.VersionTLS10, 0}, nil102 }, TLSVersionsDirective, &tlsVersions)103104 childM.Custom("ciphers", false, false, func() (interface{}, error) {105 return nil, nil106 }, TLSCiphersDirective, &baseCfg.CipherSuites)107108 childM.Custom("curves", false, false, func() (interface{}, error) {109 return nil, nil110 }, TLSCurvesDirective, &baseCfg.CurvePreferences)111112 if _, err := childM.Process(); err != nil {113 return nil, err114 }115116 baseCfg.MinVersion = tlsVersions[0]117 baseCfg.MaxVersion = tlsVersions[1]118 log.Debugf("tls: min version: %x, max version: %x", tlsVersions[0], tlsVersions[1])119120 return &TLSConfig{121 loader: loader,122 baseCfg: &baseCfg,123 }, nil124}