summaryrefslogtreecommitdiff
path: root/gemini/tls.go
blob: 1ea0f3c0fb5ffcec6c3bbeed1190580c8092ffd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package gemini

import (
	"crypto/tls"
	"errors"
)

// FileTLS builds a TLS configuration from paths to a certificate and key file.
//
// It sets parameters on the configuration to make it suitable for use with gemini.
func FileTLS(certfile string, keyfile string) (*tls.Config, error) {
	cert, err := tls.LoadX509KeyPair(certfile, keyfile)
	if err != nil {
		return nil, err
	}

	return &tls.Config{
		Certificates: []tls.Certificate{cert},
		MinVersion:   tls.VersionTLS12,
		ClientAuth:   tls.RequestClientCert,
	}, nil
}

// MultiTLS returns a *tls.Config usable for virtual hosting multiple domains.
//
// The provided configs map should be keyed on domain names, and the fallback will
// be used if the client does not support SNI, or if the requested domain isn't found.
func MultiTLS(configs map[string]*tls.Config, fallback *tls.Config) *tls.Config {
	multi := &tls.Config{
		MinVersion: tls.VersionTLS12,
		ClientAuth: tls.RequestClientCert,
		GetConfigForClient: func(info *tls.ClientHelloInfo) (*tls.Config, error) {
			conf, ok := configs[info.ServerName]
			if !ok {
				if fallback == nil {
					return nil, errors.New("no TLS config found")
				}
				conf = fallback
			}
			return conf, nil
		},
	}

	if fallback != nil {
		multi.Certificates = fallback.Certificates
	}

	return multi
}