github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/infra/conf/cfgcommon/tlscfg/tls.go (about) 1 package tlscfg 2 3 import ( 4 "encoding/base64" 5 "strings" 6 7 "github.com/golang/protobuf/proto" 8 9 "github.com/v2fly/v2ray-core/v5/common/platform/filesystem" 10 "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon" 11 "github.com/v2fly/v2ray-core/v5/transport/internet/tls" 12 ) 13 14 //go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen 15 16 type TLSConfig struct { 17 Insecure bool `json:"allowInsecure"` 18 Certs []*TLSCertConfig `json:"certificates"` 19 ServerName string `json:"serverName"` 20 ALPN *cfgcommon.StringList `json:"alpn"` 21 EnableSessionResumption bool `json:"enableSessionResumption"` 22 DisableSystemRoot bool `json:"disableSystemRoot"` 23 PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` 24 VerifyClientCertificate bool `json:"verifyClientCertificate"` 25 } 26 27 // Build implements Buildable. 28 func (c *TLSConfig) Build() (proto.Message, error) { 29 config := new(tls.Config) 30 config.Certificate = make([]*tls.Certificate, len(c.Certs)) 31 for idx, certConf := range c.Certs { 32 cert, err := certConf.Build() 33 if err != nil { 34 return nil, err 35 } 36 config.Certificate[idx] = cert 37 } 38 serverName := c.ServerName 39 config.AllowInsecure = c.Insecure 40 config.VerifyClientCertificate = c.VerifyClientCertificate 41 if len(c.ServerName) > 0 { 42 config.ServerName = serverName 43 } 44 if c.ALPN != nil && len(*c.ALPN) > 0 { 45 config.NextProtocol = []string(*c.ALPN) 46 } 47 config.EnableSessionResumption = c.EnableSessionResumption 48 config.DisableSystemRoot = c.DisableSystemRoot 49 50 if c.PinnedPeerCertificateChainSha256 != nil { 51 config.PinnedPeerCertificateChainSha256 = [][]byte{} 52 for _, v := range *c.PinnedPeerCertificateChainSha256 { 53 hashValue, err := base64.StdEncoding.DecodeString(v) 54 if err != nil { 55 return nil, err 56 } 57 config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue) 58 } 59 } 60 61 return config, nil 62 } 63 64 type TLSCertConfig struct { 65 CertFile string `json:"certificateFile"` 66 CertStr []string `json:"certificate"` 67 KeyFile string `json:"keyFile"` 68 KeyStr []string `json:"key"` 69 Usage string `json:"usage"` 70 } 71 72 // Build implements Buildable. 73 func (c *TLSCertConfig) Build() (*tls.Certificate, error) { 74 certificate := new(tls.Certificate) 75 76 cert, err := readFileOrString(c.CertFile, c.CertStr) 77 if err != nil { 78 return nil, newError("failed to parse certificate").Base(err) 79 } 80 certificate.Certificate = cert 81 82 if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { 83 key, err := readFileOrString(c.KeyFile, c.KeyStr) 84 if err != nil { 85 return nil, newError("failed to parse key").Base(err) 86 } 87 certificate.Key = key 88 } 89 90 switch strings.ToLower(c.Usage) { 91 case "encipherment": 92 certificate.Usage = tls.Certificate_ENCIPHERMENT 93 case "verify": 94 certificate.Usage = tls.Certificate_AUTHORITY_VERIFY 95 case "verifyclient": 96 certificate.Usage = tls.Certificate_AUTHORITY_VERIFY_CLIENT 97 case "issue": 98 certificate.Usage = tls.Certificate_AUTHORITY_ISSUE 99 default: 100 certificate.Usage = tls.Certificate_ENCIPHERMENT 101 } 102 103 return certificate, nil 104 } 105 106 func readFileOrString(f string, s []string) ([]byte, error) { 107 if len(f) > 0 { 108 return filesystem.ReadFile(f) 109 } 110 if len(s) > 0 { 111 return []byte(strings.Join(s, "\n")), nil 112 } 113 return nil, newError("both file and bytes are empty.") 114 }