|
|
@@ -24,9 +24,10 @@ import (
|
|
|
utls "github.com/Psiphon-Labs/utls"
|
|
|
)
|
|
|
|
|
|
+const TLS_NULL_SESSION_KEY = ""
|
|
|
+
|
|
|
// TLSClientSessionCacheWrapper is a wrapper around tls.ClientSessionCache
|
|
|
// that provides a hard-coded key for the cache.
|
|
|
-// It implements the TLSClientSessionCacheWrapper interface.
|
|
|
type TLSClientSessionCacheWrapper struct {
|
|
|
tls.ClientSessionCache
|
|
|
|
|
|
@@ -34,32 +35,54 @@ type TLSClientSessionCacheWrapper struct {
|
|
|
sessionKey string
|
|
|
}
|
|
|
|
|
|
-// WrapClientSessionCache wraps a tls.ClientSessionCache with an alternative
|
|
|
-// key, ignoring the SNI-based key that crypto/tls passes to Put/Get, which
|
|
|
-// may be incompatible with SNI obfuscation transforms.
|
|
|
+// WrapUtlsClientSessionCache wraps a tls.ClientSessionCache with an alternative
|
|
|
+// hard-coded session key, ignoring the SNI-based key that crypto/tls passes to Put/Get,
|
|
|
+// which may be incompatible with the SNI obfuscation transforms.
|
|
|
+// If the sessionKey is empty (TLS_NULL_SESSION_KEY), SetSessionKey has to be called
|
|
|
+// before using the cache.
|
|
|
func WrapClientSessionCache(
|
|
|
cache tls.ClientSessionCache,
|
|
|
hardCodedSessionKey string,
|
|
|
) *TLSClientSessionCacheWrapper {
|
|
|
-
|
|
|
return &TLSClientSessionCacheWrapper{
|
|
|
ClientSessionCache: cache,
|
|
|
sessionKey: hardCodedSessionKey,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Get retrieves the session from the cache using the hard-coded session key.
|
|
|
func (c *TLSClientSessionCacheWrapper) Get(_ string) (session *tls.ClientSessionState, ok bool) {
|
|
|
+ if c.sessionKey == "" {
|
|
|
+ return nil, false
|
|
|
+ }
|
|
|
return c.ClientSessionCache.Get(c.sessionKey)
|
|
|
}
|
|
|
|
|
|
+// Put stores the session in the cache using the hard-coded session key.
|
|
|
func (c *TLSClientSessionCacheWrapper) Put(_ string, cs *tls.ClientSessionState) {
|
|
|
+ if c.sessionKey == "" {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ cs.ResumptionState()
|
|
|
c.ClientSessionCache.Put(c.sessionKey, cs)
|
|
|
}
|
|
|
|
|
|
+// RemoveCacheEntry removes the cache entry for the hard-coded session key.
|
|
|
func (c *TLSClientSessionCacheWrapper) RemoveCacheEntry() {
|
|
|
+ if c.sessionKey == "" {
|
|
|
+ return
|
|
|
+ }
|
|
|
c.ClientSessionCache.Put(c.sessionKey, nil)
|
|
|
}
|
|
|
|
|
|
+// SetSessionKey sets the hard-coded session key if not already set.
|
|
|
+func (c *TLSClientSessionCacheWrapper) SetSessionKey(key string) {
|
|
|
+ if c.sessionKey != TLS_NULL_SESSION_KEY {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ c.sessionKey = key
|
|
|
+}
|
|
|
+
|
|
|
// UtlClientSessionCacheWrapper is a wrapper around utls.ClientSessionCache
|
|
|
// that provides a hard-coded key for the cache.
|
|
|
// It implements the TLSClientSessionCacheWrapper interface.
|
|
|
@@ -71,27 +94,48 @@ type UtlsClientSessionCacheWrapper struct {
|
|
|
}
|
|
|
|
|
|
// WrapUtlsClientSessionCache wraps a utls.ClientSessionCache with an alternative
|
|
|
-// key, ignoring the SNI-based key that crypto/tls passes to Put/Get, which
|
|
|
-// may be incompatible with SNI obfuscation transforms.
|
|
|
+// hard-coded session key, ignoring the SNI-based key that crypto/tls passes to Put/Get,
|
|
|
+// which may be incompatible with the SNI obfuscation transforms.
|
|
|
+// If the sessionKey is empty (TLS_NULL_SESSION_KEY), SetSessionKey has to be called
|
|
|
+// before using the cache.
|
|
|
func WrapUtlsClientSessionCache(
|
|
|
cache utls.ClientSessionCache,
|
|
|
hardCodedSessionKey string,
|
|
|
) *UtlsClientSessionCacheWrapper {
|
|
|
-
|
|
|
return &UtlsClientSessionCacheWrapper{
|
|
|
ClientSessionCache: cache,
|
|
|
sessionKey: hardCodedSessionKey,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Get retrieves the session from the cache using the hard-coded session key.
|
|
|
func (c *UtlsClientSessionCacheWrapper) Get(_ string) (session *utls.ClientSessionState, ok bool) {
|
|
|
+ if c.sessionKey == "" {
|
|
|
+ return nil, false
|
|
|
+ }
|
|
|
return c.ClientSessionCache.Get(c.sessionKey)
|
|
|
}
|
|
|
|
|
|
+// Put stores the session in the cache using the hard-coded session key.
|
|
|
func (c *UtlsClientSessionCacheWrapper) Put(_ string, cs *utls.ClientSessionState) {
|
|
|
+ if c.sessionKey == "" {
|
|
|
+ return
|
|
|
+ }
|
|
|
c.ClientSessionCache.Put(c.sessionKey, cs)
|
|
|
}
|
|
|
|
|
|
+// RemoveCacheEntry removes the cache entry for the hard-coded session key.
|
|
|
func (c *UtlsClientSessionCacheWrapper) RemoveCacheEntry() {
|
|
|
- c.ClientSessionCache.Put(c.sessionKey, nil)
|
|
|
+ if c.sessionKey != "" {
|
|
|
+ c.ClientSessionCache.Put(c.sessionKey, nil)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// SetSessionKey sets the hard-coded session key if not already set.
|
|
|
+// If the session key is already set, it does nothing.
|
|
|
+func (c *UtlsClientSessionCacheWrapper) SetSessionKey(key string) {
|
|
|
+ if c.sessionKey != TLS_NULL_SESSION_KEY {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ c.sessionKey = key
|
|
|
}
|