Просмотр исходного кода

Allow session ID to be specified as a config parameter

Rod Hynes 8 лет назад
Родитель
Сommit
d116a826b7
3 измененных файлов с 32 добавлено и 8 удалено
  1. 27 0
      psiphon/config.go
  2. 4 8
      psiphon/controller.go
  3. 1 0
      psiphon/server/api.go

+ 27 - 0
psiphon/config.go

@@ -27,7 +27,9 @@ import (
 	"net/http"
 	"os"
 	"strconv"
+	"strings"
 	"time"
+	"unicode"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
@@ -491,6 +493,15 @@ type Config struct {
 
 	// IgnoreHandshakeStatsRegexps skips compiling and using stats regexes.
 	IgnoreHandshakeStatsRegexps bool
+
+	// SessionID specifies a client session ID to use in the Psiphon API. The session
+	// ID should be a randomly generated value that is used only for a single session,
+	// which is defined as the period between a user starting a Psiphon client and
+	// stopping the client.
+	// A session ID must be 32 hex digits (lower case). When blank, a random session
+	// ID is automatically generated. Supply a session ID when a single client session
+	// will cross multiple Controller instances.
+	SessionID string
 }
 
 // DownloadURL specifies a URL for downloading resources along with parameters
@@ -738,6 +749,22 @@ func LoadConfig(configJson []byte) (*Config, error) {
 		config.EstablishTunnelPausePeriodSeconds = &defaultEstablishTunnelPausePeriodSeconds
 	}
 
+	if config.SessionID == "" {
+		sessionID, err := MakeSessionId()
+		if err != nil {
+			return nil, common.ContextError(err)
+		}
+		config.SessionID = sessionID
+	}
+
+	// SessionID must be PSIPHON_API_CLIENT_SESSION_ID_LENGTH lowercase hex-encoded bytes
+	if len(config.SessionID) != 2*protocol.PSIPHON_API_CLIENT_SESSION_ID_LENGTH ||
+		-1 != strings.IndexFunc(config.SessionID, func(c rune) bool {
+			return !unicode.Is(unicode.ASCII_Hex_Digit, c) || unicode.IsUpper(c)
+		}) {
+		return nil, common.ContextError(errors.New("invalid SessionID"))
+	}
+
 	return &config, nil
 }
 

+ 4 - 8
psiphon/controller.go

@@ -89,13 +89,9 @@ func NewController(config *Config) (controller *Controller, err error) {
 	// Needed by regen, at least
 	rand.Seed(int64(time.Now().Nanosecond()))
 
-	// Generate a session ID for the Psiphon server API. This session ID is
-	// used across all tunnels established by the controller.
-	sessionId, err := MakeSessionId()
-	if err != nil {
-		return nil, common.ContextError(err)
-	}
-	NoticeSessionId(sessionId)
+	// The session ID for the Psiphon server API is used across all
+	// tunnels established by the controller.
+	NoticeSessionId(config.SessionID)
 
 	// untunneledPendingConns may be used to interrupt the fetch remote server list
 	// request and other untunneled connection establishments. BindToDevice may be
@@ -117,7 +113,7 @@ func NewController(config *Config) (controller *Controller, err error) {
 
 	controller = &Controller{
 		config:    config,
-		sessionId: sessionId,
+		sessionId: config.SessionID,
 		// componentFailureSignal receives a signal from a component (including socks and
 		// http local proxies) if they unexpectedly fail. Senders should not block.
 		// Buffer allows at least one stop signal to be sent before there is a receiver.

+ 1 - 0
psiphon/server/api.go

@@ -858,6 +858,7 @@ func isServerSecret(support *SupportServices, value string) bool {
 }
 
 func isHexDigits(_ *SupportServices, value string) bool {
+	// Allows both uppercase in addition to lowercase, for legacy support.
 	return -1 == strings.IndexFunc(value, func(c rune) bool {
 		return !unicode.Is(unicode.ASCII_Hex_Digit, c)
 	})