github.com/imannamdari/v2ray-core/v5@v5.0.5/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/imannamdari/v2ray-core/v5/common/platform/filesystem"
    10  	"github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon"
    11  	"github.com/imannamdari/v2ray-core/v5/transport/internet/tls"
    12  )
    13  
    14  //go:generate go run github.com/imannamdari/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  	EnableEch                        bool                  `json:"enableEch"`
    26  	EchSetting                       *TLSEchSetting        `json:"echSetting"`
    27  }
    28  
    29  // Build implements Buildable.
    30  func (c *TLSConfig) Build() (proto.Message, error) {
    31  	config := new(tls.Config)
    32  	config.Certificate = make([]*tls.Certificate, len(c.Certs))
    33  	for idx, certConf := range c.Certs {
    34  		cert, err := certConf.Build()
    35  		if err != nil {
    36  			return nil, err
    37  		}
    38  		config.Certificate[idx] = cert
    39  	}
    40  	serverName := c.ServerName
    41  	config.AllowInsecure = c.Insecure
    42  	config.VerifyClientCertificate = c.VerifyClientCertificate
    43  	if len(c.ServerName) > 0 {
    44  		config.ServerName = serverName
    45  	}
    46  	if c.ALPN != nil && len(*c.ALPN) > 0 {
    47  		config.NextProtocol = []string(*c.ALPN)
    48  	}
    49  	config.EnableSessionResumption = c.EnableSessionResumption
    50  	config.DisableSystemRoot = c.DisableSystemRoot
    51  
    52  	if c.PinnedPeerCertificateChainSha256 != nil {
    53  		config.PinnedPeerCertificateChainSha256 = [][]byte{}
    54  		for _, v := range *c.PinnedPeerCertificateChainSha256 {
    55  			hashValue, err := base64.StdEncoding.DecodeString(v)
    56  			if err != nil {
    57  				return nil, err
    58  			}
    59  			config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue)
    60  		}
    61  	}
    62  
    63  	config.EnableEch = c.EnableEch
    64  	if c.EchSetting != nil {
    65  		config.EchSetting, _ = c.EchSetting.Build()
    66  	}
    67  
    68  	return config, nil
    69  }
    70  
    71  type TLSCertConfig struct {
    72  	CertFile string   `json:"certificateFile"`
    73  	CertStr  []string `json:"certificate"`
    74  	KeyFile  string   `json:"keyFile"`
    75  	KeyStr   []string `json:"key"`
    76  	Usage    string   `json:"usage"`
    77  }
    78  
    79  // Build implements Buildable.
    80  func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
    81  	certificate := new(tls.Certificate)
    82  
    83  	cert, err := readFileOrString(c.CertFile, c.CertStr)
    84  	if err != nil {
    85  		return nil, newError("failed to parse certificate").Base(err)
    86  	}
    87  	certificate.Certificate = cert
    88  
    89  	if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
    90  		key, err := readFileOrString(c.KeyFile, c.KeyStr)
    91  		if err != nil {
    92  			return nil, newError("failed to parse key").Base(err)
    93  		}
    94  		certificate.Key = key
    95  	}
    96  
    97  	switch strings.ToLower(c.Usage) {
    98  	case "encipherment":
    99  		certificate.Usage = tls.Certificate_ENCIPHERMENT
   100  	case "verify":
   101  		certificate.Usage = tls.Certificate_AUTHORITY_VERIFY
   102  	case "verifyclient":
   103  		certificate.Usage = tls.Certificate_AUTHORITY_VERIFY_CLIENT
   104  	case "issue":
   105  		certificate.Usage = tls.Certificate_AUTHORITY_ISSUE
   106  	default:
   107  		certificate.Usage = tls.Certificate_ENCIPHERMENT
   108  	}
   109  
   110  	return certificate, nil
   111  }
   112  
   113  func readFileOrString(f string, s []string) ([]byte, error) {
   114  	if len(f) > 0 {
   115  		return filesystem.ReadFile(f)
   116  	}
   117  	if len(s) > 0 {
   118  		return []byte(strings.Join(s, "\n")), nil
   119  	}
   120  	return nil, newError("both file and bytes are empty.")
   121  }
   122  
   123  type TLSEchSetting struct {
   124  	DnsAddr    string `json:"dnsAddr"`
   125  	InitEchKey string `json:"initEchKey"`
   126  }
   127  
   128  func (c *TLSEchSetting) Build() (*tls.ECHSetting, error) {
   129  	setting := new(tls.ECHSetting)
   130  
   131  	setting.DnsAddr = c.DnsAddr
   132  	setting.InitEchKey = c.InitEchKey
   133  
   134  	return setting, nil
   135  }