Browse Source

add support for not loading system roots. fixes #1513

Darien Raymond 6 years ago
parent
commit
974b488ab0

+ 7 - 5
infra/conf/transport_internet.go

@@ -269,11 +269,12 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
 }
 }
 
 
 type TLSConfig struct {
 type TLSConfig struct {
-	Insecure        bool             `json:"allowInsecure"`
-	InsecureCiphers bool             `json:"allowInsecureCiphers"`
-	Certs           []*TLSCertConfig `json:"certificates"`
-	ServerName      string           `json:"serverName"`
-	ALPN            *StringList      `json:"alpn"`
+	Insecure         bool             `json:"allowInsecure"`
+	InsecureCiphers  bool             `json:"allowInsecureCiphers"`
+	Certs            []*TLSCertConfig `json:"certificates"`
+	ServerName       string           `json:"serverName"`
+	ALPN             *StringList      `json:"alpn"`
+	DiableSystemRoot bool             `json:disableSystemRoot`
 }
 }
 
 
 // Build implements Buildable.
 // Build implements Buildable.
@@ -296,6 +297,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
 	if c.ALPN != nil && len(*c.ALPN) > 0 {
 	if c.ALPN != nil && len(*c.ALPN) > 0 {
 		config.NextProtocol = []string(*c.ALPN)
 		config.NextProtocol = []string(*c.ALPN)
 	}
 	}
+	config.DisableSystemRoot = c.DiableSystemRoot
 	return config, nil
 	return config, nil
 }
 }
 
 

+ 16 - 1
transport/internet/tls/config.go

@@ -29,6 +29,16 @@ func ParseCertificate(c *cert.Certificate) *Certificate {
 	}
 	}
 }
 }
 
 
+func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
+	root := x509.NewCertPool()
+	for _, cert := range c.Certificate {
+		if !root.AppendCertsFromPEM(cert.Certificate) {
+			return nil, newError("failed to append cert").AtWarning()
+		}
+	}
+	return root, nil
+}
+
 // BuildCertificates builds a list of TLS certificates from proto definition.
 // BuildCertificates builds a list of TLS certificates from proto definition.
 func (c *Config) BuildCertificates() []tls.Certificate {
 func (c *Config) BuildCertificates() []tls.Certificate {
 	certs := make([]tls.Certificate, 0, len(c.Certificate))
 	certs := make([]tls.Certificate, 0, len(c.Certificate))
@@ -158,9 +168,14 @@ func (c *Config) parseServerName() string {
 
 
 // GetTLSConfig converts this Config into tls.Config.
 // GetTLSConfig converts this Config into tls.Config.
 func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
 func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
+	root, err := c.getCertPool()
+	if err != nil {
+		newError("failed to load system root certificate").AtError().Base(err).WriteToLog()
+	}
+
 	config := &tls.Config{
 	config := &tls.Config{
 		ClientSessionCache:     globalSessionCache,
 		ClientSessionCache:     globalSessionCache,
-		RootCAs:                c.getCertPool(),
+		RootCAs:                root,
 		SessionTicketsDisabled: c.DisableSessionResumption,
 		SessionTicketsDisabled: c.DisableSessionResumption,
 	}
 	}
 	if c == nil {
 	if c == nil {

+ 41 - 30
transport/internet/tls/config.pb.go

@@ -114,10 +114,12 @@ type Config struct {
 	// Lists of string as ALPN values.
 	// Lists of string as ALPN values.
 	NextProtocol []string `protobuf:"bytes,4,rep,name=next_protocol,json=nextProtocol,proto3" json:"next_protocol,omitempty"`
 	NextProtocol []string `protobuf:"bytes,4,rep,name=next_protocol,json=nextProtocol,proto3" json:"next_protocol,omitempty"`
 	// Whether or not to disable session (ticket) resumption.
 	// Whether or not to disable session (ticket) resumption.
-	DisableSessionResumption bool     `protobuf:"varint,6,opt,name=disable_session_resumption,json=disableSessionResumption,proto3" json:"disable_session_resumption,omitempty"`
-	XXX_NoUnkeyedLiteral     struct{} `json:"-"`
-	XXX_unrecognized         []byte   `json:"-"`
-	XXX_sizecache            int32    `json:"-"`
+	DisableSessionResumption bool `protobuf:"varint,6,opt,name=disable_session_resumption,json=disableSessionResumption,proto3" json:"disable_session_resumption,omitempty"`
+	// If true, root certificates on the system will not be loaded for verification.
+	DisableSystemRoot    bool     `protobuf:"varint,7,opt,name=disable_system_root,json=disableSystemRoot,proto3" json:"disable_system_root,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
 }
 }
 
 
 func (m *Config) Reset()         { *m = Config{} }
 func (m *Config) Reset()         { *m = Config{} }
@@ -187,6 +189,13 @@ func (m *Config) GetDisableSessionResumption() bool {
 	return false
 	return false
 }
 }
 
 
+func (m *Config) GetDisableSystemRoot() bool {
+	if m != nil {
+		return m.DisableSystemRoot
+	}
+	return false
+}
+
 func init() {
 func init() {
 	proto.RegisterEnum("v2ray.core.transport.internet.tls.Certificate_Usage", Certificate_Usage_name, Certificate_Usage_value)
 	proto.RegisterEnum("v2ray.core.transport.internet.tls.Certificate_Usage", Certificate_Usage_name, Certificate_Usage_value)
 	proto.RegisterType((*Certificate)(nil), "v2ray.core.transport.internet.tls.Certificate")
 	proto.RegisterType((*Certificate)(nil), "v2ray.core.transport.internet.tls.Certificate")
@@ -198,31 +207,33 @@ func init() {
 }
 }
 
 
 var fileDescriptor_42ed70cad60a2736 = []byte{
 var fileDescriptor_42ed70cad60a2736 = []byte{
-	// 413 bytes of a gzipped FileDescriptorProto
+	// 435 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xd1, 0x6e, 0xd3, 0x30,
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xd1, 0x6e, 0xd3, 0x30,
-	0x14, 0x86, 0x49, 0x42, 0x2b, 0x76, 0xda, 0x8d, 0xc8, 0x4c, 0x28, 0xe2, 0x86, 0xac, 0x68, 0x52,
-	0xaf, 0x1c, 0x29, 0xec, 0x92, 0x1b, 0x08, 0x41, 0x0b, 0x88, 0x52, 0xb9, 0xe9, 0xa4, 0x71, 0x13,
-	0x79, 0xe6, 0x6c, 0x58, 0x4a, 0xec, 0xca, 0x76, 0x07, 0x7d, 0x25, 0x5e, 0x81, 0xc7, 0xe0, 0x85,
-	0x50, 0x93, 0xb6, 0xb4, 0x57, 0x13, 0x77, 0x3e, 0xff, 0xf9, 0xce, 0xb1, 0xff, 0xdf, 0x90, 0xde,
-	0xa7, 0x86, 0xaf, 0xa8, 0xd0, 0x4d, 0x22, 0xb4, 0xc1, 0xc4, 0x19, 0xae, 0xec, 0x42, 0x1b, 0x97,
-	0x48, 0xe5, 0xd0, 0x28, 0x74, 0x89, 0xab, 0x6d, 0x22, 0xb4, 0xba, 0x95, 0x77, 0x74, 0x61, 0xb4,
-	0xd3, 0xe4, 0x6c, 0x3b, 0x63, 0x90, 0xee, 0x78, 0xba, 0xe5, 0xa9, 0xab, 0xed, 0xe8, 0x8f, 0x07,
-	0x83, 0x0c, 0x8d, 0x93, 0xb7, 0x52, 0x70, 0x87, 0x24, 0x3e, 0x28, 0x23, 0x2f, 0xf6, 0xc6, 0x43,
-	0x76, 0x40, 0x84, 0x10, 0x7c, 0xc2, 0x55, 0xe4, 0xb7, 0x9d, 0xf5, 0x91, 0x7c, 0x84, 0xde, 0xd2,
-	0xf2, 0x3b, 0x8c, 0x82, 0xd8, 0x1b, 0x9f, 0xa4, 0x17, 0xf4, 0xc1, 0x6b, 0xe9, 0xde, 0x42, 0x3a,
-	0x5f, 0xcf, 0xb2, 0x6e, 0xc5, 0xe8, 0x3d, 0xf4, 0xda, 0x9a, 0x84, 0x30, 0xcc, 0x27, 0x59, 0x31,
-	0xbd, 0xcc, 0xd9, 0xe7, 0x7c, 0x52, 0x86, 0x8f, 0xc8, 0x29, 0x84, 0x6f, 0xe7, 0xe5, 0xe5, 0x17,
-	0x56, 0x94, 0xd7, 0xd5, 0x55, 0xce, 0x8a, 0x0f, 0xd7, 0xa1, 0x47, 0x9e, 0xc1, 0xd3, 0x7f, 0x6a,
-	0x31, 0x9b, 0xcd, 0xf3, 0xd0, 0x1f, 0xfd, 0xf6, 0xa1, 0x9f, 0xb5, 0x49, 0x90, 0x73, 0x38, 0xe1,
-	0x75, 0xad, 0x7f, 0x54, 0x52, 0x59, 0x14, 0x4b, 0xd3, 0x79, 0x7a, 0xc2, 0x8e, 0x5b, 0xb5, 0xd8,
-	0x88, 0xe4, 0x02, 0x9e, 0x1f, 0x62, 0x95, 0x90, 0x8b, 0xef, 0x68, 0x6c, 0xd4, 0x6b, 0xf1, 0xd3,
-	0x03, 0x3c, 0xeb, 0x7a, 0x64, 0x0a, 0x03, 0xb1, 0x97, 0x96, 0x1f, 0x07, 0xe3, 0x41, 0x4a, 0xff,
-	0xcf, 0x3f, 0xdb, 0x5f, 0x41, 0x5e, 0xc2, 0xc0, 0xa2, 0xb9, 0x47, 0x53, 0x29, 0xde, 0x74, 0x89,
-	0x1e, 0x31, 0xe8, 0xa4, 0x09, 0x6f, 0x90, 0xbc, 0x82, 0x63, 0x85, 0x3f, 0x5d, 0xd5, 0xfe, 0xb0,
-	0xd0, 0x75, 0xf4, 0x38, 0x0e, 0xc6, 0x47, 0x6c, 0xb8, 0x16, 0xa7, 0x1b, 0x8d, 0xbc, 0x81, 0x17,
-	0xdf, 0xa4, 0xe5, 0x37, 0x35, 0x56, 0x16, 0xad, 0x95, 0x5a, 0x55, 0x06, 0xed, 0xb2, 0x59, 0x38,
-	0xa9, 0x55, 0xd4, 0x6f, 0x1d, 0x45, 0x1b, 0x62, 0xd6, 0x01, 0x6c, 0xd7, 0x7f, 0xc7, 0xe0, 0x5c,
-	0xe8, 0xe6, 0x61, 0x17, 0x53, 0xef, 0x6b, 0xe0, 0x6a, 0xfb, 0xcb, 0x3f, 0xbb, 0x4a, 0x19, 0x5f,
-	0xd1, 0x6c, 0x8d, 0x96, 0x3b, 0xb4, 0xd8, 0xa2, 0x65, 0x6d, 0x6f, 0xfa, 0xed, 0x7b, 0x5f, 0xff,
-	0x0d, 0x00, 0x00, 0xff, 0xff, 0x80, 0x63, 0x12, 0xa7, 0xc7, 0x02, 0x00, 0x00,
+	0x14, 0x86, 0x49, 0x43, 0x0b, 0x3b, 0xed, 0x46, 0xf0, 0x26, 0x14, 0x71, 0x43, 0x56, 0x34, 0xa9,
+	0x57, 0x8e, 0x14, 0x76, 0xc9, 0x0d, 0x84, 0xa0, 0x05, 0x44, 0xa9, 0xdc, 0x74, 0xd2, 0xb8, 0x89,
+	0x32, 0x73, 0x36, 0x2c, 0x25, 0x76, 0x65, 0xbb, 0x83, 0xbe, 0x12, 0xaf, 0xc3, 0x63, 0xf0, 0x12,
+	0xa8, 0x4e, 0x5b, 0xda, 0xab, 0x69, 0x77, 0x39, 0xff, 0xff, 0xfd, 0x27, 0xfa, 0x8f, 0x21, 0xb9,
+	0x4b, 0x74, 0xb5, 0xa4, 0x5c, 0x35, 0x31, 0x57, 0x1a, 0x63, 0xab, 0x2b, 0x69, 0xe6, 0x4a, 0xdb,
+	0x58, 0x48, 0x8b, 0x5a, 0xa2, 0x8d, 0x6d, 0x6d, 0x62, 0xae, 0xe4, 0x8d, 0xb8, 0xa5, 0x73, 0xad,
+	0xac, 0x22, 0xa7, 0x9b, 0x8c, 0x46, 0xba, 0xe5, 0xe9, 0x86, 0xa7, 0xb6, 0x36, 0xc3, 0x3f, 0x1e,
+	0xf4, 0x53, 0xd4, 0x56, 0xdc, 0x08, 0x5e, 0x59, 0x24, 0xd1, 0xde, 0x18, 0x7a, 0x91, 0x37, 0x1a,
+	0xb0, 0x3d, 0x22, 0x00, 0xff, 0x33, 0x2e, 0xc3, 0x8e, 0x73, 0x56, 0x9f, 0xe4, 0x13, 0x74, 0x17,
+	0xa6, 0xba, 0xc5, 0xd0, 0x8f, 0xbc, 0xd1, 0x51, 0x72, 0x4e, 0xef, 0xfd, 0x2d, 0xdd, 0x59, 0x48,
+	0x67, 0xab, 0x2c, 0x6b, 0x57, 0x0c, 0x3f, 0x40, 0xd7, 0xcd, 0x24, 0x80, 0x41, 0x36, 0x4e, 0xf3,
+	0xc9, 0x45, 0xc6, 0xbe, 0x64, 0xe3, 0x22, 0x78, 0x44, 0x4e, 0x20, 0x78, 0x37, 0x2b, 0x2e, 0xbe,
+	0xb2, 0xbc, 0xb8, 0x2a, 0x2f, 0x33, 0x96, 0x7f, 0xbc, 0x0a, 0x3c, 0x72, 0x0c, 0xcf, 0xfe, 0xab,
+	0xf9, 0x74, 0x3a, 0xcb, 0x82, 0xce, 0xf0, 0x6f, 0x07, 0x7a, 0xa9, 0xbb, 0x04, 0x39, 0x83, 0xa3,
+	0xaa, 0xae, 0xd5, 0xcf, 0x52, 0x48, 0x83, 0x7c, 0xa1, 0xdb, 0x4e, 0x4f, 0xd9, 0xa1, 0x53, 0xf3,
+	0xb5, 0x48, 0xce, 0xe1, 0xc5, 0x3e, 0x56, 0x72, 0x31, 0xff, 0x81, 0xda, 0x84, 0x5d, 0x87, 0x9f,
+	0xec, 0xe1, 0x69, 0xeb, 0x91, 0x09, 0xf4, 0xf9, 0xce, 0xb5, 0x3a, 0x91, 0x3f, 0xea, 0x27, 0xf4,
+	0x61, 0xfd, 0xd9, 0xee, 0x0a, 0xf2, 0x0a, 0xfa, 0x06, 0xf5, 0x1d, 0xea, 0x52, 0x56, 0x4d, 0x7b,
+	0xd1, 0x03, 0x06, 0xad, 0x34, 0xae, 0x1a, 0x24, 0xaf, 0xe1, 0x50, 0xe2, 0x2f, 0x5b, 0xba, 0x17,
+	0xe6, 0xaa, 0x0e, 0x1f, 0x47, 0xfe, 0xe8, 0x80, 0x0d, 0x56, 0xe2, 0x64, 0xad, 0x91, 0xb7, 0xf0,
+	0xf2, 0xbb, 0x30, 0xd5, 0x75, 0x8d, 0xa5, 0x41, 0x63, 0x84, 0x92, 0xa5, 0x46, 0xb3, 0x68, 0xe6,
+	0x56, 0x28, 0x19, 0xf6, 0x5c, 0xa3, 0x70, 0x4d, 0x4c, 0x5b, 0x80, 0x6d, 0x7d, 0x42, 0xe1, 0x78,
+	0x9b, 0x5e, 0x1a, 0x8b, 0x4d, 0xa9, 0x95, 0xb2, 0xe1, 0x13, 0x17, 0x7b, 0xbe, 0x89, 0x39, 0x87,
+	0x29, 0x65, 0xdf, 0x33, 0x38, 0xe3, 0xaa, 0xb9, 0xbf, 0xf5, 0xc4, 0xfb, 0xe6, 0xdb, 0xda, 0xfc,
+	0xee, 0x9c, 0x5e, 0x26, 0xac, 0x5a, 0xd2, 0x74, 0x85, 0x16, 0x5b, 0x34, 0xdf, 0xa0, 0x45, 0x6d,
+	0xae, 0x7b, 0xae, 0xdf, 0x9b, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x58, 0x74, 0x54, 0xf7,
+	0x02, 0x00, 0x00,
 }
 }

+ 3 - 0
transport/internet/tls/config.proto

@@ -40,4 +40,7 @@ message Config {
 
 
   // Whether or not to disable session (ticket) resumption.
   // Whether or not to disable session (ticket) resumption.
   bool disable_session_resumption = 6;
   bool disable_session_resumption = 6;
+
+  // If true, root certificates on the system will not be loaded for verification.
+  bool disable_system_root = 7;
 }
 }

+ 29 - 39
transport/internet/tls/config_other.go

@@ -4,60 +4,50 @@
 package tls
 package tls
 
 
 import (
 import (
-	"bytes"
 	"crypto/x509"
 	"crypto/x509"
 	"sync"
 	"sync"
 )
 )
 
 
-type certPoolCache struct {
+type rootCertsCache struct {
 	sync.Mutex
 	sync.Mutex
-	once       sync.Once
-	pool       *x509.CertPool
-	extraCerts [][]byte
+	pool *x509.CertPool
 }
 }
 
 
-func (c *certPoolCache) hasCert(cert []byte) bool {
-	for _, xCert := range c.extraCerts {
-		if bytes.Equal(xCert, cert) {
-			return true
-		}
+func (c *rootCertsCache) load() (*x509.CertPool, error) {
+	c.Lock()
+	defer c.Unlock()
+
+	if c.pool != nil {
+		return c.pool, nil
 	}
 	}
-	return false
+
+	pool, err := x509.SystemCertPool()
+	if err != nil {
+		return nil, err
+	}
+	c.pool = pool
+	return pool, nil
 }
 }
 
 
-func (c *certPoolCache) get(extraCerts []*Certificate) *x509.CertPool {
-	c.once.Do(func() {
-		pool, err := x509.SystemCertPool()
-		if err != nil {
-			newError("failed to get system cert pool.").Base(err).WriteToLog()
-			return
-		}
-		c.pool = pool
-	})
+var rootCerts rootCertsCache
 
 
-	if c.pool == nil {
-		return nil
+func (c *Config) getCertPool() (*x509.CertPool, error) {
+	if c.DisableSystemRoot {
+		return c.loadSelfCertPool()
 	}
 	}
 
 
-	if len(extraCerts) == 0 {
-		return c.pool
+	if len(c.Certificate) == 0 {
+		return rootCerts.load()
 	}
 	}
 
 
-	c.Lock()
-	defer c.Unlock()
-
-	for _, cert := range extraCerts {
-		if !c.hasCert(cert.Certificate) {
-			c.pool.AppendCertsFromPEM(cert.Certificate)
-			c.extraCerts = append(c.extraCerts, cert.Certificate)
+	pool, err := x509.SystemCertPool()
+	if err != nil {
+		return nil, newError("system root").AtWarning().Base(err)
+	}
+	for _, cert := range c.Certificate {
+		if !pool.AppendCertsFromPEM(cert.Certificate) {
+			return nil, newError("append cert to root").AtWarning().Base(err)
 		}
 		}
 	}
 	}
-
-	return c.pool
-}
-
-var combineCertPool certPoolCache
-
-func (c *Config) getCertPool() *x509.CertPool {
-	return combineCertPool.get(c.Certificate)
+	return pool, err
 }
 }

+ 5 - 1
transport/internet/tls/config_windows.go

@@ -5,6 +5,10 @@ package tls
 
 
 import "crypto/x509"
 import "crypto/x509"
 
 
-func (c *Config) getCertPool() *x509.CertPool {
+func (c *Config) getCertPool() (*x509.CertPool, error) {
+	if c.DisableSystemRoot {
+		return c.loadSelfCertPool()
+	}
+
 	return nil
 	return nil
 }
 }