get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/opts.go (about)

     1  // Copyright 2012-2024 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package server
    15  
    16  import (
    17  	"context"
    18  	"crypto/tls"
    19  	"crypto/x509"
    20  	"errors"
    21  	"flag"
    22  	"fmt"
    23  	"math"
    24  	"net"
    25  	"net/url"
    26  	"os"
    27  	"path"
    28  	"path/filepath"
    29  	"regexp"
    30  	"runtime"
    31  	"strconv"
    32  	"strings"
    33  	"sync/atomic"
    34  	"time"
    35  
    36  	"get.pme.sh/pnats/conf"
    37  	"get.pme.sh/pnats/server/certidp"
    38  	"get.pme.sh/pnats/server/certstore"
    39  	"github.com/nats-io/jwt/v2"
    40  	"github.com/nats-io/nkeys"
    41  )
    42  
    43  var allowUnknownTopLevelField = int32(0)
    44  
    45  // NoErrOnUnknownFields can be used to change the behavior the processing
    46  // of a configuration file. By default, an error is reported if unknown
    47  // fields are found. If `noError` is set to true, no error will be reported
    48  // if top-level unknown fields are found.
    49  func NoErrOnUnknownFields(noError bool) {
    50  	var val int32
    51  	if noError {
    52  		val = int32(1)
    53  	}
    54  	atomic.StoreInt32(&allowUnknownTopLevelField, val)
    55  }
    56  
    57  // PinnedCertSet is a set of lower case hex-encoded sha256 of DER encoded SubjectPublicKeyInfo
    58  type PinnedCertSet map[string]struct{}
    59  
    60  // ClusterOpts are options for clusters.
    61  // NOTE: This structure is no longer used for monitoring endpoints
    62  // and json tags are deprecated and may be removed in the future.
    63  type ClusterOpts struct {
    64  	Name              string            `json:"-"`
    65  	Host              string            `json:"addr,omitempty"`
    66  	Port              int               `json:"cluster_port,omitempty"`
    67  	Username          string            `json:"-"`
    68  	Password          string            `json:"-"`
    69  	AuthTimeout       float64           `json:"auth_timeout,omitempty"`
    70  	Permissions       *RoutePermissions `json:"-"`
    71  	TLSTimeout        float64           `json:"-"`
    72  	TLSConfig         *tls.Config       `json:"-"`
    73  	TLSMap            bool              `json:"-"`
    74  	TLSCheckKnownURLs bool              `json:"-"`
    75  	TLSPinnedCerts    PinnedCertSet     `json:"-"`
    76  	ListenStr         string            `json:"-"`
    77  	Advertise         string            `json:"-"`
    78  	NoAdvertise       bool              `json:"-"`
    79  	ConnectRetries    int               `json:"-"`
    80  	PoolSize          int               `json:"-"`
    81  	PinnedAccounts    []string          `json:"-"`
    82  	Compression       CompressionOpts   `json:"-"`
    83  	PingInterval      time.Duration     `json:"-"`
    84  	MaxPingsOut       int               `json:"-"`
    85  
    86  	// Not exported (used in tests)
    87  	resolver netResolver
    88  	// Snapshot of configured TLS options.
    89  	tlsConfigOpts *TLSConfigOpts
    90  }
    91  
    92  // CompressionOpts defines the compression mode and optional configuration.
    93  type CompressionOpts struct {
    94  	Mode string
    95  	// If `Mode` is set to CompressionS2Auto, RTTThresholds provides the
    96  	// thresholds at which the compression level will go from
    97  	// CompressionS2Uncompressed to CompressionS2Fast, CompressionS2Better
    98  	// or CompressionS2Best. If a given level is not desired, specify 0
    99  	// for this slot. For instance, the slice []{0, 10ms, 20ms} means that
   100  	// for any RTT up to 10ms included the compression level will be
   101  	// CompressionS2Fast, then from ]10ms..20ms], the level will be selected
   102  	// as CompressionS2Better. Anything above 20ms will result in picking
   103  	// the CompressionS2Best compression level.
   104  	RTTThresholds []time.Duration
   105  }
   106  
   107  // GatewayOpts are options for gateways.
   108  // NOTE: This structure is no longer used for monitoring endpoints
   109  // and json tags are deprecated and may be removed in the future.
   110  type GatewayOpts struct {
   111  	Name              string               `json:"name"`
   112  	Host              string               `json:"addr,omitempty"`
   113  	Port              int                  `json:"port,omitempty"`
   114  	Username          string               `json:"-"`
   115  	Password          string               `json:"-"`
   116  	AuthTimeout       float64              `json:"auth_timeout,omitempty"`
   117  	TLSConfig         *tls.Config          `json:"-"`
   118  	TLSTimeout        float64              `json:"tls_timeout,omitempty"`
   119  	TLSMap            bool                 `json:"-"`
   120  	TLSCheckKnownURLs bool                 `json:"-"`
   121  	TLSPinnedCerts    PinnedCertSet        `json:"-"`
   122  	Advertise         string               `json:"advertise,omitempty"`
   123  	ConnectRetries    int                  `json:"connect_retries,omitempty"`
   124  	Gateways          []*RemoteGatewayOpts `json:"gateways,omitempty"`
   125  	RejectUnknown     bool                 `json:"reject_unknown,omitempty"` // config got renamed to reject_unknown_cluster
   126  
   127  	// Not exported, for tests.
   128  	resolver         netResolver
   129  	sendQSubsBufSize int
   130  
   131  	// Snapshot of configured TLS options.
   132  	tlsConfigOpts *TLSConfigOpts
   133  }
   134  
   135  // RemoteGatewayOpts are options for connecting to a remote gateway
   136  // NOTE: This structure is no longer used for monitoring endpoints
   137  // and json tags are deprecated and may be removed in the future.
   138  type RemoteGatewayOpts struct {
   139  	Name          string      `json:"name"`
   140  	TLSConfig     *tls.Config `json:"-"`
   141  	TLSTimeout    float64     `json:"tls_timeout,omitempty"`
   142  	URLs          []*url.URL  `json:"urls,omitempty"`
   143  	tlsConfigOpts *TLSConfigOpts
   144  }
   145  
   146  // LeafNodeOpts are options for a given server to accept leaf node connections and/or connect to a remote cluster.
   147  type LeafNodeOpts struct {
   148  	Host              string        `json:"addr,omitempty"`
   149  	Port              int           `json:"port,omitempty"`
   150  	Username          string        `json:"-"`
   151  	Password          string        `json:"-"`
   152  	Nkey              string        `json:"-"`
   153  	Account           string        `json:"-"`
   154  	Users             []*User       `json:"-"`
   155  	AuthTimeout       float64       `json:"auth_timeout,omitempty"`
   156  	TLSConfig         *tls.Config   `json:"-"`
   157  	TLSTimeout        float64       `json:"tls_timeout,omitempty"`
   158  	TLSMap            bool          `json:"-"`
   159  	TLSPinnedCerts    PinnedCertSet `json:"-"`
   160  	TLSHandshakeFirst bool          `json:"-"`
   161  	Advertise         string        `json:"-"`
   162  	NoAdvertise       bool          `json:"-"`
   163  	ReconnectInterval time.Duration `json:"-"`
   164  
   165  	// Compression options
   166  	Compression CompressionOpts `json:"-"`
   167  
   168  	// For solicited connections to other clusters/superclusters.
   169  	Remotes []*RemoteLeafOpts `json:"remotes,omitempty"`
   170  
   171  	// This is the minimum version that is accepted for remote connections.
   172  	// Note that since the server version in the CONNECT protocol was added
   173  	// only starting at v2.8.0, any version below that will be rejected
   174  	// (since empty version string in CONNECT would fail the "version at
   175  	// least" test).
   176  	MinVersion string
   177  
   178  	// Not exported, for tests.
   179  	resolver    netResolver
   180  	dialTimeout time.Duration
   181  	connDelay   time.Duration
   182  
   183  	// Snapshot of configured TLS options.
   184  	tlsConfigOpts *TLSConfigOpts
   185  }
   186  
   187  // SignatureHandler is used to sign a nonce from the server while
   188  // authenticating with Nkeys. The callback should sign the nonce and
   189  // return the JWT and the raw signature.
   190  type SignatureHandler func([]byte) (string, []byte, error)
   191  
   192  // RemoteLeafOpts are options for connecting to a remote server as a leaf node.
   193  type RemoteLeafOpts struct {
   194  	LocalAccount      string           `json:"local_account,omitempty"`
   195  	NoRandomize       bool             `json:"-"`
   196  	URLs              []*url.URL       `json:"urls,omitempty"`
   197  	Credentials       string           `json:"-"`
   198  	Nkey              string           `json:"-"`
   199  	SignatureCB       SignatureHandler `json:"-"`
   200  	TLS               bool             `json:"-"`
   201  	TLSConfig         *tls.Config      `json:"-"`
   202  	TLSTimeout        float64          `json:"tls_timeout,omitempty"`
   203  	TLSHandshakeFirst bool             `json:"-"`
   204  	Hub               bool             `json:"hub,omitempty"`
   205  	DenyImports       []string         `json:"-"`
   206  	DenyExports       []string         `json:"-"`
   207  
   208  	// Compression options for this remote. Each remote could have a different
   209  	// setting and also be different from the LeafNode options.
   210  	Compression CompressionOpts `json:"-"`
   211  
   212  	// When an URL has the "ws" (or "wss") scheme, then the server will initiate the
   213  	// connection as a websocket connection. By default, the websocket frames will be
   214  	// masked (as if this server was a websocket client to the remote server). The
   215  	// NoMasking option will change this behavior and will send umasked frames.
   216  	Websocket struct {
   217  		Compression bool `json:"-"`
   218  		NoMasking   bool `json:"-"`
   219  	}
   220  
   221  	tlsConfigOpts *TLSConfigOpts
   222  
   223  	// If we are clustered and our local account has JetStream, if apps are accessing
   224  	// a stream or consumer leader through this LN and it gets dropped, the apps will
   225  	// not be able to work. This tells the system to migrate the leaders away from this server.
   226  	// This only changes leader for R>1 assets.
   227  	JetStreamClusterMigrate bool `json:"jetstream_cluster_migrate,omitempty"`
   228  }
   229  
   230  type JSLimitOpts struct {
   231  	MaxRequestBatch int
   232  	MaxAckPending   int
   233  	MaxHAAssets     int
   234  	Duplicates      time.Duration
   235  }
   236  
   237  // AuthCallout option used to map external AuthN to NATS based AuthZ.
   238  type AuthCallout struct {
   239  	// Must be a public account Nkey.
   240  	Issuer string
   241  	// Account to be used for sending requests.
   242  	Account string
   243  	// Users that will bypass auth_callout and be used for the auth service itself.
   244  	AuthUsers []string
   245  	// XKey is a public xkey for the authorization service.
   246  	// This will enable encryption for server requests and the authorization service responses.
   247  	XKey string
   248  }
   249  
   250  // NetworkIntercept is an interface that allows to intercept the dial and listen
   251  type NetworkIntercept interface {
   252  	DialTimeoutCause(network, address string, timeout time.Duration, cause string) (net.Conn, error)
   253  	ListenCause(network, address, cause string) (net.Listener, error)
   254  }
   255  
   256  // Options block for nats-server.
   257  // NOTE: This structure is no longer used for monitoring endpoints
   258  // and json tags are deprecated and may be removed in the future.
   259  type Options struct {
   260  	ConfigFile            string        `json:"-"`
   261  	ServerName            string        `json:"server_name"`
   262  	Host                  string        `json:"addr"`
   263  	Port                  int           `json:"port"`
   264  	DontListen            bool          `json:"dont_listen"`
   265  	ClientAdvertise       string        `json:"-"`
   266  	Trace                 bool          `json:"-"`
   267  	Debug                 bool          `json:"-"`
   268  	TraceVerbose          bool          `json:"-"`
   269  	NoLog                 bool          `json:"-"`
   270  	NoSigs                bool          `json:"-"`
   271  	NoSublistCache        bool          `json:"-"`
   272  	NoHeaderSupport       bool          `json:"-"`
   273  	DisableShortFirstPing bool          `json:"-"`
   274  	Logtime               bool          `json:"-"`
   275  	LogtimeUTC            bool          `json:"-"`
   276  	MaxConn               int           `json:"max_connections"`
   277  	MaxSubs               int           `json:"max_subscriptions,omitempty"`
   278  	MaxSubTokens          uint8         `json:"-"`
   279  	Nkeys                 []*NkeyUser   `json:"-"`
   280  	Users                 []*User       `json:"-"`
   281  	Accounts              []*Account    `json:"-"`
   282  	NoAuthUser            string        `json:"-"`
   283  	SystemAccount         string        `json:"-"`
   284  	NoSystemAccount       bool          `json:"-"`
   285  	Username              string        `json:"-"`
   286  	Password              string        `json:"-"`
   287  	Authorization         string        `json:"-"`
   288  	AuthCallout           *AuthCallout  `json:"-"`
   289  	PingInterval          time.Duration `json:"ping_interval"`
   290  	MaxPingsOut           int           `json:"ping_max"`
   291  	HTTPHost              string        `json:"http_host"`
   292  	HTTPPort              int           `json:"http_port"`
   293  	HTTPBasePath          string        `json:"http_base_path"`
   294  	HTTPSPort             int           `json:"https_port"`
   295  	AuthTimeout           float64       `json:"auth_timeout"`
   296  	MaxControlLine        int32         `json:"max_control_line"`
   297  	MaxPayload            int32         `json:"max_payload"`
   298  	MaxPending            int64         `json:"max_pending"`
   299  	Cluster               ClusterOpts   `json:"cluster,omitempty"`
   300  	Gateway               GatewayOpts   `json:"gateway,omitempty"`
   301  	LeafNode              LeafNodeOpts  `json:"leaf,omitempty"`
   302  	JetStream             bool          `json:"jetstream"`
   303  	JetStreamMaxMemory    int64         `json:"-"`
   304  	JetStreamMaxStore     int64         `json:"-"`
   305  	JetStreamDomain       string        `json:"-"`
   306  	JetStreamExtHint      string        `json:"-"`
   307  	JetStreamKey          string        `json:"-"`
   308  	JetStreamOldKey       string        `json:"-"`
   309  	JetStreamCipher       StoreCipher   `json:"-"`
   310  	JetStreamUniqueTag    string
   311  	JetStreamLimits       JSLimitOpts
   312  	JetStreamMaxCatchup   int64
   313  	StoreDir              string            `json:"-"`
   314  	SyncInterval          time.Duration     `json:"-"`
   315  	SyncAlways            bool              `json:"-"`
   316  	JsAccDefaultDomain    map[string]string `json:"-"` // account to domain name mapping
   317  	Websocket             WebsocketOpts     `json:"-"`
   318  	MQTT                  MQTTOpts          `json:"-"`
   319  	ProfPort              int               `json:"-"`
   320  	ProfBlockRate         int               `json:"-"`
   321  	PidFile               string            `json:"-"`
   322  	PortsFileDir          string            `json:"-"`
   323  	LogFile               string            `json:"-"`
   324  	LogSizeLimit          int64             `json:"-"`
   325  	LogMaxFiles           int64             `json:"-"`
   326  	Syslog                bool              `json:"-"`
   327  	RemoteSyslog          string            `json:"-"`
   328  	Routes                []*url.URL        `json:"-"`
   329  	RoutesStr             string            `json:"-"`
   330  	TLSTimeout            float64           `json:"tls_timeout"`
   331  	TLS                   bool              `json:"-"`
   332  	TLSVerify             bool              `json:"-"`
   333  	TLSMap                bool              `json:"-"`
   334  	TLSCert               string            `json:"-"`
   335  	TLSKey                string            `json:"-"`
   336  	TLSCaCert             string            `json:"-"`
   337  	TLSConfig             *tls.Config       `json:"-"`
   338  	TLSPinnedCerts        PinnedCertSet     `json:"-"`
   339  	TLSRateLimit          int64             `json:"-"`
   340  	// When set to true, the server will perform the TLS handshake before
   341  	// sending the INFO protocol. For clients that are not configured
   342  	// with a similar option, their connection will fail with some sort
   343  	// of timeout or EOF error since they are expecting to receive an
   344  	// INFO protocol first.
   345  	TLSHandshakeFirst bool `json:"-"`
   346  	// If TLSHandshakeFirst is true and this value is strictly positive,
   347  	// the server will wait for that amount of time for the TLS handshake
   348  	// to start before falling back to previous behavior of sending the
   349  	// INFO protocol first. It allows for a mix of newer clients that can
   350  	// require a TLS handshake first, and older clients that can't.
   351  	TLSHandshakeFirstFallback time.Duration `json:"-"`
   352  	AllowNonTLS               bool          `json:"-"`
   353  	WriteDeadline             time.Duration `json:"-"`
   354  	MaxClosedClients          int           `json:"-"`
   355  	LameDuckDuration          time.Duration `json:"-"`
   356  	LameDuckGracePeriod       time.Duration `json:"-"`
   357  
   358  	// MaxTracedMsgLen is the maximum printable length for traced messages.
   359  	MaxTracedMsgLen int `json:"-"`
   360  
   361  	// Operating a trusted NATS server
   362  	TrustedKeys              []string              `json:"-"`
   363  	TrustedOperators         []*jwt.OperatorClaims `json:"-"`
   364  	AccountResolver          AccountResolver       `json:"-"`
   365  	AccountResolverTLSConfig *tls.Config           `json:"-"`
   366  
   367  	// AlwaysEnableNonce will always present a nonce to new connections
   368  	// typically used by custom Authentication implementations who embeds
   369  	// the server and so not presented as a configuration option
   370  	AlwaysEnableNonce bool
   371  
   372  	CustomClientAuthentication Authentication `json:"-"`
   373  	CustomRouterAuthentication Authentication `json:"-"`
   374  
   375  	// Dial and Listen overrides.
   376  	NetworkIntercept NetworkIntercept `json:"-"`
   377  
   378  	// CheckConfig configuration file syntax test was successful and exit.
   379  	CheckConfig bool `json:"-"`
   380  
   381  	// DisableJetStreamBanner will not print the ascii art on startup for JetStream enabled servers
   382  	DisableJetStreamBanner bool `json:"-"`
   383  
   384  	// ConnectErrorReports specifies the number of failed attempts
   385  	// at which point server should report the failure of an initial
   386  	// connection to a route, gateway or leaf node.
   387  	// See DEFAULT_CONNECT_ERROR_REPORTS for default value.
   388  	ConnectErrorReports int
   389  
   390  	// ReconnectErrorReports is similar to ConnectErrorReports except
   391  	// that this applies to reconnect events.
   392  	ReconnectErrorReports int
   393  
   394  	// Tags describing the server. They will be included in varz
   395  	// and used as a filter criteria for some system requests.
   396  	Tags jwt.TagList `json:"-"`
   397  
   398  	// OCSPConfig enables OCSP Stapling in the server.
   399  	OCSPConfig    *OCSPConfig
   400  	tlsConfigOpts *TLSConfigOpts
   401  
   402  	// private fields, used to know if bool options are explicitly
   403  	// defined in config and/or command line params.
   404  	inConfig  map[string]bool
   405  	inCmdLine map[string]bool
   406  
   407  	// private fields for operator mode
   408  	operatorJWT            []string
   409  	resolverPreloads       map[string]string
   410  	resolverPinnedAccounts map[string]struct{}
   411  
   412  	// private fields, used for testing
   413  	gatewaysSolicitDelay time.Duration
   414  	overrideProto        int
   415  
   416  	// JetStream
   417  	maxMemSet   bool
   418  	maxStoreSet bool
   419  	syncSet     bool
   420  
   421  	// OCSP Cache config enables next-gen cache for OCSP features
   422  	OCSPCacheConfig *OCSPResponseCacheConfig
   423  
   424  	// Used to mark that we had a top level authorization block.
   425  	authBlockDefined bool
   426  }
   427  
   428  // WebsocketOpts are options for websocket
   429  type WebsocketOpts struct {
   430  	// The server will accept websocket client connections on this hostname/IP.
   431  	Host string
   432  	// The server will accept websocket client connections on this port.
   433  	Port int
   434  	// The host:port to advertise to websocket clients in the cluster.
   435  	Advertise string
   436  
   437  	// If no user name is provided when a client connects, will default to the
   438  	// matching user from the global list of users in `Options.Users`.
   439  	NoAuthUser string
   440  
   441  	// Name of the cookie, which if present in WebSocket upgrade headers,
   442  	// will be treated as JWT during CONNECT phase as long as
   443  	// "jwt" specified in the CONNECT options is missing or empty.
   444  	JWTCookie string
   445  
   446  	// Name of the cookie, which if present in WebSocket upgrade headers,
   447  	// will be treated as Username during CONNECT phase as long as
   448  	// "user" specified in the CONNECT options is missing or empty.
   449  	UsernameCookie string
   450  
   451  	// Name of the cookie, which if present in WebSocket upgrade headers,
   452  	// will be treated as Password during CONNECT phase as long as
   453  	// "pass" specified in the CONNECT options is missing or empty.
   454  	PasswordCookie string
   455  
   456  	// Name of the cookie, which if present in WebSocket upgrade headers,
   457  	// will be treated as Token during CONNECT phase as long as
   458  	// "auth_token" specified in the CONNECT options is missing or empty.
   459  	// Note that when this is useful for passing a JWT to an cuth callout
   460  	// when the server uses delegated authentication ("operator mode") or
   461  	// when using delegated authentication, but the auth callout validates some
   462  	// other JWT or string. Note that this does map to an actual server-wide
   463  	// "auth_token", note that using it for that purpose is greatly discouraged.
   464  	TokenCookie string
   465  
   466  	// Authentication section. If anything is configured in this section,
   467  	// it will override the authorization configuration of regular clients.
   468  	Username string
   469  	Password string
   470  	Token    string
   471  
   472  	// Timeout for the authentication process.
   473  	AuthTimeout float64
   474  
   475  	// By default the server will enforce the use of TLS. If no TLS configuration
   476  	// is provided, you need to explicitly set NoTLS to true to allow the server
   477  	// to start without TLS configuration. Note that if a TLS configuration is
   478  	// present, this boolean is ignored and the server will run the Websocket
   479  	// server with that TLS configuration.
   480  	// Running without TLS is less secure since Websocket clients that use bearer
   481  	// tokens will send them in clear. So this should not be used in production.
   482  	NoTLS bool
   483  
   484  	// TLS configuration is required.
   485  	TLSConfig *tls.Config
   486  	// If true, map certificate values for authentication purposes.
   487  	TLSMap bool
   488  
   489  	// When present, accepted client certificates (verify/verify_and_map) must be in this list
   490  	TLSPinnedCerts PinnedCertSet
   491  
   492  	// If true, the Origin header must match the request's host.
   493  	SameOrigin bool
   494  
   495  	// Only origins in this list will be accepted. If empty and
   496  	// SameOrigin is false, any origin is accepted.
   497  	AllowedOrigins []string
   498  
   499  	// If set to true, the server will negotiate with clients
   500  	// if compression can be used. If this is false, no compression
   501  	// will be used (both in server and clients) since it has to
   502  	// be negotiated between both endpoints
   503  	Compression bool
   504  
   505  	// Total time allowed for the server to read the client request
   506  	// and write the response back to the client. This include the
   507  	// time needed for the TLS Handshake.
   508  	HandshakeTimeout time.Duration
   509  
   510  	// Snapshot of configured TLS options.
   511  	tlsConfigOpts *TLSConfigOpts
   512  }
   513  
   514  // MQTTOpts are options for MQTT
   515  type MQTTOpts struct {
   516  	// The server will accept MQTT client connections on this hostname/IP.
   517  	Host string
   518  	// The server will accept MQTT client connections on this port.
   519  	Port int
   520  
   521  	// If no user name is provided when a client connects, will default to the
   522  	// matching user from the global list of users in `Options.Users`.
   523  	NoAuthUser string
   524  
   525  	// Authentication section. If anything is configured in this section,
   526  	// it will override the authorization configuration of regular clients.
   527  	Username string
   528  	Password string
   529  	Token    string
   530  
   531  	// JetStream domain mqtt is supposed to pick up
   532  	JsDomain string
   533  
   534  	// Number of replicas for MQTT streams.
   535  	// Negative or 0 value means that the server(s) will pick a replica
   536  	// number based on the known size of the cluster (but capped at 3).
   537  	// Note that if an account was already connected, the stream's replica
   538  	// count is not modified. Use the NATS CLI to update the count if desired.
   539  	StreamReplicas int
   540  
   541  	// Number of replicas for MQTT consumers.
   542  	// Negative or 0 value means that there is no override and the consumer
   543  	// will have the same replica factor that the stream it belongs to.
   544  	// If a value is specified, it will require to be lower than the stream
   545  	// replicas count (lower than StreamReplicas if specified, but also lower
   546  	// than the automatic value determined by cluster size).
   547  	// Note that existing consumers are not modified.
   548  	//
   549  	// UPDATE: This is no longer used while messages stream has interest policy retention
   550  	// which requires consumer replica count to match the parent stream.
   551  	ConsumerReplicas int
   552  
   553  	// Indicate if the consumers should be created with memory storage.
   554  	// Note that existing consumers are not modified.
   555  	ConsumerMemoryStorage bool
   556  
   557  	// If specified will have the system auto-cleanup the consumers after being
   558  	// inactive for the specified amount of time.
   559  	ConsumerInactiveThreshold time.Duration
   560  
   561  	// Timeout for the authentication process.
   562  	AuthTimeout float64
   563  
   564  	// TLS configuration is required.
   565  	TLSConfig *tls.Config
   566  	// If true, map certificate values for authentication purposes.
   567  	TLSMap bool
   568  	// Timeout for the TLS handshake
   569  	TLSTimeout float64
   570  	// Set of allowable certificates
   571  	TLSPinnedCerts PinnedCertSet
   572  
   573  	// AckWait is the amount of time after which a QoS 1 or 2 message sent to a
   574  	// client is redelivered as a DUPLICATE if the server has not received the
   575  	// PUBACK on the original Packet Identifier. The same value applies to
   576  	// PubRel redelivery. The value has to be positive. Zero will cause the
   577  	// server to use the default value (30 seconds). Note that changes to this
   578  	// option is applied only to new MQTT subscriptions (or sessions for
   579  	// PubRels).
   580  	AckWait time.Duration
   581  
   582  	// MaxAckPending is the amount of QoS 1 and 2 messages (combined) the server
   583  	// can send to a subscription without receiving any PUBACK for those
   584  	// messages. The valid range is [0..65535].
   585  	//
   586  	// The total of subscriptions' MaxAckPending on a given session cannot
   587  	// exceed 65535. Attempting to create a subscription that would bring the
   588  	// total above the limit would result in the server returning 0x80 in the
   589  	// SUBACK for this subscription.
   590  	//
   591  	// Due to how the NATS Server handles the MQTT "#" wildcard, each
   592  	// subscription ending with "#" will use 2 times the MaxAckPending value.
   593  	// Note that changes to this option is applied only to new subscriptions.
   594  	MaxAckPending uint16
   595  
   596  	// Snapshot of configured TLS options.
   597  	tlsConfigOpts *TLSConfigOpts
   598  
   599  	// rejectQoS2Pub tells the MQTT client to not accept QoS2 PUBLISH, instead
   600  	// error and terminate the connection.
   601  	rejectQoS2Pub bool
   602  
   603  	// downgradeQOS2Sub tells the MQTT client to downgrade QoS2 SUBSCRIBE
   604  	// requests to QoS1.
   605  	downgradeQoS2Sub bool
   606  }
   607  
   608  type netResolver interface {
   609  	LookupHost(ctx context.Context, host string) ([]string, error)
   610  }
   611  
   612  // Clone performs a deep copy of the Options struct, returning a new clone
   613  // with all values copied.
   614  func (o *Options) Clone() *Options {
   615  	if o == nil {
   616  		return nil
   617  	}
   618  	clone := &Options{}
   619  	*clone = *o
   620  	if o.Users != nil {
   621  		clone.Users = make([]*User, len(o.Users))
   622  		for i, user := range o.Users {
   623  			clone.Users[i] = user.clone()
   624  		}
   625  	}
   626  	if o.Nkeys != nil {
   627  		clone.Nkeys = make([]*NkeyUser, len(o.Nkeys))
   628  		for i, nkey := range o.Nkeys {
   629  			clone.Nkeys[i] = nkey.clone()
   630  		}
   631  	}
   632  
   633  	if o.Routes != nil {
   634  		clone.Routes = deepCopyURLs(o.Routes)
   635  	}
   636  	if o.TLSConfig != nil {
   637  		clone.TLSConfig = o.TLSConfig.Clone()
   638  	}
   639  	if o.Cluster.TLSConfig != nil {
   640  		clone.Cluster.TLSConfig = o.Cluster.TLSConfig.Clone()
   641  	}
   642  	if o.Gateway.TLSConfig != nil {
   643  		clone.Gateway.TLSConfig = o.Gateway.TLSConfig.Clone()
   644  	}
   645  	if len(o.Gateway.Gateways) > 0 {
   646  		clone.Gateway.Gateways = make([]*RemoteGatewayOpts, len(o.Gateway.Gateways))
   647  		for i, g := range o.Gateway.Gateways {
   648  			clone.Gateway.Gateways[i] = g.clone()
   649  		}
   650  	}
   651  	// FIXME(dlc) - clone leaf node stuff.
   652  	return clone
   653  }
   654  
   655  func deepCopyURLs(urls []*url.URL) []*url.URL {
   656  	if urls == nil {
   657  		return nil
   658  	}
   659  	curls := make([]*url.URL, len(urls))
   660  	for i, u := range urls {
   661  		cu := &url.URL{}
   662  		*cu = *u
   663  		curls[i] = cu
   664  	}
   665  	return curls
   666  }
   667  
   668  // Configuration file authorization section.
   669  type authorization struct {
   670  	// Singles
   671  	user  string
   672  	pass  string
   673  	token string
   674  	nkey  string
   675  	acc   string
   676  	// Multiple Nkeys/Users
   677  	nkeys              []*NkeyUser
   678  	users              []*User
   679  	timeout            float64
   680  	defaultPermissions *Permissions
   681  	// Auth Callouts
   682  	callout *AuthCallout
   683  }
   684  
   685  // TLSConfigOpts holds the parsed tls config information,
   686  // used with flag parsing
   687  type TLSConfigOpts struct {
   688  	CertFile          string
   689  	KeyFile           string
   690  	CaFile            string
   691  	Verify            bool
   692  	Insecure          bool
   693  	Map               bool
   694  	TLSCheckKnownURLs bool
   695  	HandshakeFirst    bool          // Indicate that the TLS handshake should occur first, before sending the INFO protocol.
   696  	FallbackDelay     time.Duration // Where supported, indicates how long to wait for the handshake before falling back to sending the INFO protocol first.
   697  	Timeout           float64
   698  	RateLimit         int64
   699  	Ciphers           []uint16
   700  	CurvePreferences  []tls.CurveID
   701  	PinnedCerts       PinnedCertSet
   702  	CertStore         certstore.StoreType
   703  	CertMatchBy       certstore.MatchByType
   704  	CertMatch         string
   705  	OCSPPeerConfig    *certidp.OCSPPeerConfig
   706  	Certificates      []*TLSCertPairOpt
   707  }
   708  
   709  // TLSCertPairOpt are the paths to a certificate and private key.
   710  type TLSCertPairOpt struct {
   711  	CertFile string
   712  	KeyFile  string
   713  }
   714  
   715  // OCSPConfig represents the options of OCSP stapling options.
   716  type OCSPConfig struct {
   717  	// Mode defines the policy for OCSP stapling.
   718  	Mode OCSPMode
   719  
   720  	// OverrideURLs is the http URL endpoint used to get OCSP staples.
   721  	OverrideURLs []string
   722  }
   723  
   724  var tlsUsage = `
   725  TLS configuration is specified in the tls section of a configuration file:
   726  
   727  e.g.
   728  
   729      tls {
   730          cert_file:      "./certs/server-cert.pem"
   731          key_file:       "./certs/server-key.pem"
   732          ca_file:        "./certs/ca.pem"
   733          verify:         true
   734          verify_and_map: true
   735  
   736          cipher_suites: [
   737              "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
   738              "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
   739          ]
   740          curve_preferences: [
   741              "CurveP256",
   742              "CurveP384",
   743              "CurveP521"
   744          ]
   745      }
   746  
   747  Available cipher suites include:
   748  `
   749  
   750  // ProcessConfigFile processes a configuration file.
   751  // FIXME(dlc): A bit hacky
   752  func ProcessConfigFile(configFile string) (*Options, error) {
   753  	opts := &Options{}
   754  	if err := opts.ProcessConfigFile(configFile); err != nil {
   755  		// If only warnings then continue and return the options.
   756  		if cerr, ok := err.(*processConfigErr); ok && len(cerr.Errors()) == 0 {
   757  			return opts, nil
   758  		}
   759  
   760  		return nil, err
   761  	}
   762  	return opts, nil
   763  }
   764  
   765  // token is an item parsed from the configuration.
   766  type token interface {
   767  	Value() interface{}
   768  	Line() int
   769  	IsUsedVariable() bool
   770  	SourceFile() string
   771  	Position() int
   772  }
   773  
   774  // unwrapValue can be used to get the token and value from an item
   775  // to be able to report the line number in case of an incorrect
   776  // configuration.
   777  // also stores the token in lastToken for use in convertPanicToError
   778  func unwrapValue(v interface{}, lastToken *token) (token, interface{}) {
   779  	switch tk := v.(type) {
   780  	case token:
   781  		if lastToken != nil {
   782  			*lastToken = tk
   783  		}
   784  		return tk, tk.Value()
   785  	default:
   786  		return nil, v
   787  	}
   788  }
   789  
   790  // use in defer to recover from panic and turn it into an error associated with last token
   791  func convertPanicToErrorList(lastToken *token, errors *[]error) {
   792  	// only recover if an error can be stored
   793  	if errors == nil {
   794  		return
   795  	} else if err := recover(); err == nil {
   796  		return
   797  	} else if lastToken != nil && *lastToken != nil {
   798  		*errors = append(*errors, &configErr{*lastToken, fmt.Sprint(err)})
   799  	} else {
   800  		*errors = append(*errors, fmt.Errorf("encountered panic without a token %v", err))
   801  	}
   802  }
   803  
   804  // use in defer to recover from panic and turn it into an error associated with last token
   805  func convertPanicToError(lastToken *token, e *error) {
   806  	// only recover if an error can be stored
   807  	if e == nil || *e != nil {
   808  		return
   809  	} else if err := recover(); err == nil {
   810  		return
   811  	} else if lastToken != nil && *lastToken != nil {
   812  		*e = &configErr{*lastToken, fmt.Sprint(err)}
   813  	} else {
   814  		*e = fmt.Errorf("%v", err)
   815  	}
   816  }
   817  
   818  // configureSystemAccount configures a system account
   819  // if present in the configuration.
   820  func configureSystemAccount(o *Options, m map[string]interface{}) (retErr error) {
   821  	var lt token
   822  	defer convertPanicToError(&lt, &retErr)
   823  	configure := func(v interface{}) error {
   824  		tk, v := unwrapValue(v, &lt)
   825  		sa, ok := v.(string)
   826  		if !ok {
   827  			return &configErr{tk, "system account name must be a string"}
   828  		}
   829  		o.SystemAccount = sa
   830  		return nil
   831  	}
   832  
   833  	if v, ok := m["system_account"]; ok {
   834  		return configure(v)
   835  	} else if v, ok := m["system"]; ok {
   836  		return configure(v)
   837  	}
   838  
   839  	return nil
   840  }
   841  
   842  // ProcessConfigFile updates the Options structure with options
   843  // present in the given configuration file.
   844  // This version is convenient if one wants to set some default
   845  // options and then override them with what is in the config file.
   846  // For instance, this version allows you to do something such as:
   847  //
   848  // opts := &Options{Debug: true}
   849  // opts.ProcessConfigFile(myConfigFile)
   850  //
   851  // If the config file contains "debug: false", after this call,
   852  // opts.Debug would really be false. It would be impossible to
   853  // achieve that with the non receiver ProcessConfigFile() version,
   854  // since one would not know after the call if "debug" was not present
   855  // or was present but set to false.
   856  func (o *Options) ProcessConfigFile(configFile string) error {
   857  	o.ConfigFile = configFile
   858  	if configFile == _EMPTY_ {
   859  		return nil
   860  	}
   861  	m, err := conf.ParseFileWithChecks(configFile)
   862  	if err != nil {
   863  		return err
   864  	}
   865  	// Collect all errors and warnings and report them all together.
   866  	errors := make([]error, 0)
   867  	warnings := make([]error, 0)
   868  	if len(m) == 0 {
   869  		warnings = append(warnings, fmt.Errorf("%s: config has no values or is empty", configFile))
   870  	}
   871  
   872  	// First check whether a system account has been defined,
   873  	// as that is a condition for other features to be enabled.
   874  	if err := configureSystemAccount(o, m); err != nil {
   875  		errors = append(errors, err)
   876  	}
   877  
   878  	for k, v := range m {
   879  		o.processConfigFileLine(k, v, &errors, &warnings)
   880  	}
   881  
   882  	if len(errors) > 0 || len(warnings) > 0 {
   883  		return &processConfigErr{
   884  			errors:   errors,
   885  			warnings: warnings,
   886  		}
   887  	}
   888  
   889  	return nil
   890  }
   891  
   892  func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error, warnings *[]error) {
   893  	var lt token
   894  	defer convertPanicToErrorList(&lt, errors)
   895  
   896  	tk, v := unwrapValue(v, &lt)
   897  	switch strings.ToLower(k) {
   898  	case "listen":
   899  		hp, err := parseListen(v)
   900  		if err != nil {
   901  			*errors = append(*errors, &configErr{tk, err.Error()})
   902  			return
   903  		}
   904  		o.Host = hp.host
   905  		o.Port = hp.port
   906  	case "client_advertise":
   907  		o.ClientAdvertise = v.(string)
   908  	case "port":
   909  		o.Port = int(v.(int64))
   910  	case "server_name":
   911  		o.ServerName = v.(string)
   912  	case "host", "net":
   913  		o.Host = v.(string)
   914  	case "debug":
   915  		o.Debug = v.(bool)
   916  		trackExplicitVal(o, &o.inConfig, "Debug", o.Debug)
   917  	case "trace":
   918  		o.Trace = v.(bool)
   919  		trackExplicitVal(o, &o.inConfig, "Trace", o.Trace)
   920  	case "trace_verbose":
   921  		o.TraceVerbose = v.(bool)
   922  		o.Trace = v.(bool)
   923  		trackExplicitVal(o, &o.inConfig, "TraceVerbose", o.TraceVerbose)
   924  		trackExplicitVal(o, &o.inConfig, "Trace", o.Trace)
   925  	case "logtime":
   926  		o.Logtime = v.(bool)
   927  		trackExplicitVal(o, &o.inConfig, "Logtime", o.Logtime)
   928  	case "logtime_utc":
   929  		o.LogtimeUTC = v.(bool)
   930  		trackExplicitVal(o, &o.inConfig, "LogtimeUTC", o.LogtimeUTC)
   931  	case "mappings", "maps":
   932  		gacc := NewAccount(globalAccountName)
   933  		o.Accounts = append(o.Accounts, gacc)
   934  		err := parseAccountMappings(tk, gacc, errors, warnings)
   935  		if err != nil {
   936  			*errors = append(*errors, err)
   937  			return
   938  		}
   939  	case "disable_sublist_cache", "no_sublist_cache":
   940  		o.NoSublistCache = v.(bool)
   941  	case "accounts":
   942  		err := parseAccounts(tk, o, errors, warnings)
   943  		if err != nil {
   944  			*errors = append(*errors, err)
   945  			return
   946  		}
   947  	case "authorization":
   948  		auth, err := parseAuthorization(tk, o, errors, warnings)
   949  		if err != nil {
   950  			*errors = append(*errors, err)
   951  			return
   952  		}
   953  		o.authBlockDefined = true
   954  		o.Username = auth.user
   955  		o.Password = auth.pass
   956  		o.Authorization = auth.token
   957  		o.AuthTimeout = auth.timeout
   958  		o.AuthCallout = auth.callout
   959  
   960  		if (auth.user != _EMPTY_ || auth.pass != _EMPTY_) && auth.token != _EMPTY_ {
   961  			err := &configErr{tk, "Cannot have a user/pass and token"}
   962  			*errors = append(*errors, err)
   963  			return
   964  		}
   965  		// In case parseAccounts() was done first, we need to check for duplicates.
   966  		unames := setupUsersAndNKeysDuplicateCheckMap(o)
   967  		// Check for multiple users defined.
   968  		// Note: auth.users will be != nil as long as `users: []` is present
   969  		// in the authorization block, even if empty, and will also account for
   970  		// nkey users. We also check for users/nkeys that may have been already
   971  		// added in parseAccounts() (which means they will be in unames)
   972  		if auth.users != nil || len(unames) > 0 {
   973  			if auth.user != _EMPTY_ {
   974  				err := &configErr{tk, "Can not have a single user/pass and a users array"}
   975  				*errors = append(*errors, err)
   976  				return
   977  			}
   978  			if auth.token != _EMPTY_ {
   979  				err := &configErr{tk, "Can not have a token and a users array"}
   980  				*errors = append(*errors, err)
   981  				return
   982  			}
   983  			// Now check that if we have users, there is no duplicate, including
   984  			// users that may have been configured in parseAccounts().
   985  			if len(auth.users) > 0 {
   986  				for _, u := range auth.users {
   987  					if _, ok := unames[u.Username]; ok {
   988  						err := &configErr{tk, fmt.Sprintf("Duplicate user %q detected", u.Username)}
   989  						*errors = append(*errors, err)
   990  						return
   991  					}
   992  					unames[u.Username] = struct{}{}
   993  				}
   994  				// Users may have been added from Accounts parsing, so do an append here
   995  				o.Users = append(o.Users, auth.users...)
   996  			}
   997  		}
   998  		// Check for nkeys
   999  		if len(auth.nkeys) > 0 {
  1000  			for _, u := range auth.nkeys {
  1001  				if _, ok := unames[u.Nkey]; ok {
  1002  					err := &configErr{tk, fmt.Sprintf("Duplicate nkey %q detected", u.Nkey)}
  1003  					*errors = append(*errors, err)
  1004  					return
  1005  				}
  1006  				unames[u.Nkey] = struct{}{}
  1007  			}
  1008  			// NKeys may have been added from Accounts parsing, so do an append here
  1009  			o.Nkeys = append(o.Nkeys, auth.nkeys...)
  1010  		}
  1011  	case "http":
  1012  		hp, err := parseListen(v)
  1013  		if err != nil {
  1014  			err := &configErr{tk, err.Error()}
  1015  			*errors = append(*errors, err)
  1016  			return
  1017  		}
  1018  		o.HTTPHost = hp.host
  1019  		o.HTTPPort = hp.port
  1020  	case "https":
  1021  		hp, err := parseListen(v)
  1022  		if err != nil {
  1023  			err := &configErr{tk, err.Error()}
  1024  			*errors = append(*errors, err)
  1025  			return
  1026  		}
  1027  		o.HTTPHost = hp.host
  1028  		o.HTTPSPort = hp.port
  1029  	case "http_port", "monitor_port":
  1030  		o.HTTPPort = int(v.(int64))
  1031  	case "https_port":
  1032  		o.HTTPSPort = int(v.(int64))
  1033  	case "http_base_path":
  1034  		o.HTTPBasePath = v.(string)
  1035  	case "cluster":
  1036  		err := parseCluster(tk, o, errors, warnings)
  1037  		if err != nil {
  1038  			*errors = append(*errors, err)
  1039  			return
  1040  		}
  1041  	case "gateway":
  1042  		if err := parseGateway(tk, o, errors, warnings); err != nil {
  1043  			*errors = append(*errors, err)
  1044  			return
  1045  		}
  1046  	case "leaf", "leafnodes":
  1047  		err := parseLeafNodes(tk, o, errors, warnings)
  1048  		if err != nil {
  1049  			*errors = append(*errors, err)
  1050  			return
  1051  		}
  1052  	case "store_dir", "storedir":
  1053  		// Check if JetStream configuration is also setting the storage directory.
  1054  		if o.StoreDir != _EMPTY_ {
  1055  			*errors = append(*errors, &configErr{tk, "Duplicate 'store_dir' configuration"})
  1056  			return
  1057  		}
  1058  		o.StoreDir = v.(string)
  1059  	case "jetstream":
  1060  		err := parseJetStream(tk, o, errors, warnings)
  1061  		if err != nil {
  1062  			*errors = append(*errors, err)
  1063  			return
  1064  		}
  1065  	case "logfile", "log_file":
  1066  		o.LogFile = v.(string)
  1067  	case "logfile_size_limit", "log_size_limit":
  1068  		o.LogSizeLimit = v.(int64)
  1069  	case "logfile_max_num", "log_max_num":
  1070  		o.LogMaxFiles = v.(int64)
  1071  	case "syslog":
  1072  		o.Syslog = v.(bool)
  1073  		trackExplicitVal(o, &o.inConfig, "Syslog", o.Syslog)
  1074  	case "remote_syslog":
  1075  		o.RemoteSyslog = v.(string)
  1076  	case "pidfile", "pid_file":
  1077  		o.PidFile = v.(string)
  1078  	case "ports_file_dir":
  1079  		o.PortsFileDir = v.(string)
  1080  	case "prof_port":
  1081  		o.ProfPort = int(v.(int64))
  1082  	case "prof_block_rate":
  1083  		o.ProfBlockRate = int(v.(int64))
  1084  	case "max_control_line":
  1085  		if v.(int64) > 1<<31-1 {
  1086  			err := &configErr{tk, fmt.Sprintf("%s value is too big", k)}
  1087  			*errors = append(*errors, err)
  1088  			return
  1089  		}
  1090  		o.MaxControlLine = int32(v.(int64))
  1091  	case "max_payload":
  1092  		if v.(int64) > 1<<31-1 {
  1093  			err := &configErr{tk, fmt.Sprintf("%s value is too big", k)}
  1094  			*errors = append(*errors, err)
  1095  			return
  1096  		}
  1097  		o.MaxPayload = int32(v.(int64))
  1098  	case "max_pending":
  1099  		o.MaxPending = v.(int64)
  1100  	case "max_connections", "max_conn":
  1101  		o.MaxConn = int(v.(int64))
  1102  	case "max_traced_msg_len":
  1103  		o.MaxTracedMsgLen = int(v.(int64))
  1104  	case "max_subscriptions", "max_subs":
  1105  		o.MaxSubs = int(v.(int64))
  1106  	case "max_sub_tokens", "max_subscription_tokens":
  1107  		if n := v.(int64); n > math.MaxUint8 {
  1108  			err := &configErr{tk, fmt.Sprintf("%s value is too big", k)}
  1109  			*errors = append(*errors, err)
  1110  			return
  1111  		} else if n <= 0 {
  1112  			err := &configErr{tk, fmt.Sprintf("%s value can not be negative", k)}
  1113  			*errors = append(*errors, err)
  1114  			return
  1115  		} else {
  1116  			o.MaxSubTokens = uint8(n)
  1117  		}
  1118  	case "ping_interval":
  1119  		o.PingInterval = parseDuration("ping_interval", tk, v, errors, warnings)
  1120  	case "ping_max":
  1121  		o.MaxPingsOut = int(v.(int64))
  1122  	case "tls":
  1123  		tc, err := parseTLS(tk, true)
  1124  		if err != nil {
  1125  			*errors = append(*errors, err)
  1126  			return
  1127  		}
  1128  		if o.TLSConfig, err = GenTLSConfig(tc); err != nil {
  1129  			err := &configErr{tk, err.Error()}
  1130  			*errors = append(*errors, err)
  1131  			return
  1132  		}
  1133  		o.TLSTimeout = tc.Timeout
  1134  		o.TLSMap = tc.Map
  1135  		o.TLSPinnedCerts = tc.PinnedCerts
  1136  		o.TLSRateLimit = tc.RateLimit
  1137  		o.TLSHandshakeFirst = tc.HandshakeFirst
  1138  		o.TLSHandshakeFirstFallback = tc.FallbackDelay
  1139  
  1140  		// Need to keep track of path of the original TLS config
  1141  		// and certs path for OCSP Stapling monitoring.
  1142  		o.tlsConfigOpts = tc
  1143  	case "ocsp":
  1144  		switch vv := v.(type) {
  1145  		case bool:
  1146  			if vv {
  1147  				// Default is Auto which honors Must Staple status request
  1148  				// but does not shutdown the server in case it is revoked,
  1149  				// letting the client choose whether to trust or not the server.
  1150  				o.OCSPConfig = &OCSPConfig{Mode: OCSPModeAuto}
  1151  			} else {
  1152  				o.OCSPConfig = &OCSPConfig{Mode: OCSPModeNever}
  1153  			}
  1154  		case map[string]interface{}:
  1155  			ocsp := &OCSPConfig{Mode: OCSPModeAuto}
  1156  
  1157  			for kk, kv := range vv {
  1158  				_, v = unwrapValue(kv, &tk)
  1159  				switch kk {
  1160  				case "mode":
  1161  					mode := v.(string)
  1162  					switch {
  1163  					case strings.EqualFold(mode, "always"):
  1164  						ocsp.Mode = OCSPModeAlways
  1165  					case strings.EqualFold(mode, "must"):
  1166  						ocsp.Mode = OCSPModeMust
  1167  					case strings.EqualFold(mode, "never"):
  1168  						ocsp.Mode = OCSPModeNever
  1169  					case strings.EqualFold(mode, "auto"):
  1170  						ocsp.Mode = OCSPModeAuto
  1171  					default:
  1172  						*errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing ocsp config: unsupported ocsp mode %T", mode)})
  1173  					}
  1174  				case "urls":
  1175  					urls := v.([]string)
  1176  					ocsp.OverrideURLs = urls
  1177  				case "url":
  1178  					url := v.(string)
  1179  					ocsp.OverrideURLs = []string{url}
  1180  				default:
  1181  					*errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing ocsp config: unsupported field %T", kk)})
  1182  					return
  1183  				}
  1184  			}
  1185  			o.OCSPConfig = ocsp
  1186  		default:
  1187  			*errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing ocsp config: unsupported type %T", v)})
  1188  			return
  1189  		}
  1190  	case "allow_non_tls":
  1191  		o.AllowNonTLS = v.(bool)
  1192  	case "write_deadline":
  1193  		o.WriteDeadline = parseDuration("write_deadline", tk, v, errors, warnings)
  1194  	case "lame_duck_duration":
  1195  		dur, err := time.ParseDuration(v.(string))
  1196  		if err != nil {
  1197  			err := &configErr{tk, fmt.Sprintf("error parsing lame_duck_duration: %v", err)}
  1198  			*errors = append(*errors, err)
  1199  			return
  1200  		}
  1201  		if dur < 30*time.Second {
  1202  			err := &configErr{tk, fmt.Sprintf("invalid lame_duck_duration of %v, minimum is 30 seconds", dur)}
  1203  			*errors = append(*errors, err)
  1204  			return
  1205  		}
  1206  		o.LameDuckDuration = dur
  1207  	case "lame_duck_grace_period":
  1208  		dur, err := time.ParseDuration(v.(string))
  1209  		if err != nil {
  1210  			err := &configErr{tk, fmt.Sprintf("error parsing lame_duck_grace_period: %v", err)}
  1211  			*errors = append(*errors, err)
  1212  			return
  1213  		}
  1214  		if dur < 0 {
  1215  			err := &configErr{tk, "invalid lame_duck_grace_period, needs to be positive"}
  1216  			*errors = append(*errors, err)
  1217  			return
  1218  		}
  1219  		o.LameDuckGracePeriod = dur
  1220  	case "operator", "operators", "roots", "root", "root_operators", "root_operator":
  1221  		opFiles := []string{}
  1222  		switch v := v.(type) {
  1223  		case string:
  1224  			opFiles = append(opFiles, v)
  1225  		case []string:
  1226  			opFiles = append(opFiles, v...)
  1227  		default:
  1228  			err := &configErr{tk, fmt.Sprintf("error parsing operators: unsupported type %T", v)}
  1229  			*errors = append(*errors, err)
  1230  		}
  1231  		// Assume for now these are file names, but they can also be the JWT itself inline.
  1232  		o.TrustedOperators = make([]*jwt.OperatorClaims, 0, len(opFiles))
  1233  		for _, fname := range opFiles {
  1234  			theJWT, opc, err := readOperatorJWT(fname)
  1235  			if err != nil {
  1236  				err := &configErr{tk, fmt.Sprintf("error parsing operator JWT: %v", err)}
  1237  				*errors = append(*errors, err)
  1238  				continue
  1239  			}
  1240  			o.operatorJWT = append(o.operatorJWT, theJWT)
  1241  			o.TrustedOperators = append(o.TrustedOperators, opc)
  1242  		}
  1243  		if len(o.TrustedOperators) == 1 {
  1244  			// In case "resolver" is defined as well, it takes precedence
  1245  			if o.AccountResolver == nil {
  1246  				if accUrl, err := parseURL(o.TrustedOperators[0].AccountServerURL, "account resolver"); err == nil {
  1247  					// nsc automatically appends "/accounts" during nsc push
  1248  					o.AccountResolver, _ = NewURLAccResolver(accUrl.String() + "/accounts")
  1249  				}
  1250  			}
  1251  			// In case "system_account" is defined as well, it takes precedence
  1252  			if o.SystemAccount == _EMPTY_ {
  1253  				o.SystemAccount = o.TrustedOperators[0].SystemAccount
  1254  			}
  1255  		}
  1256  	case "resolver", "account_resolver", "accounts_resolver":
  1257  		switch v := v.(type) {
  1258  		case string:
  1259  			// "resolver" takes precedence over value obtained from "operator".
  1260  			// Clear so that parsing errors are not silently ignored.
  1261  			o.AccountResolver = nil
  1262  			memResolverRe := regexp.MustCompile(`(?i)(MEM|MEMORY)\s*`)
  1263  			resolverRe := regexp.MustCompile(`(?i)(?:URL){1}(?:\({1}\s*"?([^\s"]*)"?\s*\){1})?\s*`)
  1264  			if memResolverRe.MatchString(v) {
  1265  				o.AccountResolver = &MemAccResolver{}
  1266  			} else if items := resolverRe.FindStringSubmatch(v); len(items) == 2 {
  1267  				url := items[1]
  1268  				_, err := parseURL(url, "account resolver")
  1269  				if err != nil {
  1270  					*errors = append(*errors, &configErr{tk, err.Error()})
  1271  					return
  1272  				}
  1273  				if ur, err := NewURLAccResolver(url); err != nil {
  1274  					err := &configErr{tk, err.Error()}
  1275  					*errors = append(*errors, err)
  1276  					return
  1277  				} else {
  1278  					o.AccountResolver = ur
  1279  				}
  1280  			}
  1281  		case map[string]interface{}:
  1282  			del := false
  1283  			hdel := false
  1284  			hdel_set := false
  1285  			dir := _EMPTY_
  1286  			dirType := _EMPTY_
  1287  			limit := int64(0)
  1288  			ttl := time.Duration(0)
  1289  			sync := time.Duration(0)
  1290  			opts := []DirResOption{}
  1291  			var err error
  1292  			if v, ok := v["dir"]; ok {
  1293  				_, v := unwrapValue(v, &lt)
  1294  				dir = v.(string)
  1295  			}
  1296  			if v, ok := v["type"]; ok {
  1297  				_, v := unwrapValue(v, &lt)
  1298  				dirType = v.(string)
  1299  			}
  1300  			if v, ok := v["allow_delete"]; ok {
  1301  				_, v := unwrapValue(v, &lt)
  1302  				del = v.(bool)
  1303  			}
  1304  			if v, ok := v["hard_delete"]; ok {
  1305  				_, v := unwrapValue(v, &lt)
  1306  				hdel_set = true
  1307  				hdel = v.(bool)
  1308  			}
  1309  			if v, ok := v["limit"]; ok {
  1310  				_, v := unwrapValue(v, &lt)
  1311  				limit = v.(int64)
  1312  			}
  1313  			if v, ok := v["ttl"]; ok {
  1314  				_, v := unwrapValue(v, &lt)
  1315  				ttl, err = time.ParseDuration(v.(string))
  1316  			}
  1317  			if v, ok := v["interval"]; err == nil && ok {
  1318  				_, v := unwrapValue(v, &lt)
  1319  				sync, err = time.ParseDuration(v.(string))
  1320  			}
  1321  			if v, ok := v["timeout"]; err == nil && ok {
  1322  				_, v := unwrapValue(v, &lt)
  1323  				var to time.Duration
  1324  				if to, err = time.ParseDuration(v.(string)); err == nil {
  1325  					opts = append(opts, FetchTimeout(to))
  1326  				}
  1327  			}
  1328  			if err != nil {
  1329  				*errors = append(*errors, &configErr{tk, err.Error()})
  1330  				return
  1331  			}
  1332  
  1333  			checkDir := func() {
  1334  				if dir == _EMPTY_ {
  1335  					*errors = append(*errors, &configErr{tk, "dir has no value and needs to point to a directory"})
  1336  					return
  1337  				}
  1338  				if info, _ := os.Stat(dir); info != nil && (!info.IsDir() || info.Mode().Perm()&(1<<(uint(7))) == 0) {
  1339  					*errors = append(*errors, &configErr{tk, "dir needs to point to an accessible directory"})
  1340  					return
  1341  				}
  1342  			}
  1343  
  1344  			var res AccountResolver
  1345  			switch strings.ToUpper(dirType) {
  1346  			case "CACHE":
  1347  				checkDir()
  1348  				if sync != 0 {
  1349  					*errors = append(*errors, &configErr{tk, "CACHE does not accept sync"})
  1350  				}
  1351  				if del {
  1352  					*errors = append(*errors, &configErr{tk, "CACHE does not accept allow_delete"})
  1353  				}
  1354  				if hdel_set {
  1355  					*errors = append(*errors, &configErr{tk, "CACHE does not accept hard_delete"})
  1356  				}
  1357  				res, err = NewCacheDirAccResolver(dir, limit, ttl, opts...)
  1358  			case "FULL":
  1359  				checkDir()
  1360  				if ttl != 0 {
  1361  					*errors = append(*errors, &configErr{tk, "FULL does not accept ttl"})
  1362  				}
  1363  				if hdel_set && !del {
  1364  					*errors = append(*errors, &configErr{tk, "hard_delete has no effect without delete"})
  1365  				}
  1366  				delete := NoDelete
  1367  				if del {
  1368  					if hdel {
  1369  						delete = HardDelete
  1370  					} else {
  1371  						delete = RenameDeleted
  1372  					}
  1373  				}
  1374  				res, err = NewDirAccResolver(dir, limit, sync, delete, opts...)
  1375  			case "MEM", "MEMORY":
  1376  				res = &MemAccResolver{}
  1377  			}
  1378  			if err != nil {
  1379  				*errors = append(*errors, &configErr{tk, err.Error()})
  1380  				return
  1381  			}
  1382  			o.AccountResolver = res
  1383  		default:
  1384  			err := &configErr{tk, fmt.Sprintf("error parsing operator resolver, wrong type %T", v)}
  1385  			*errors = append(*errors, err)
  1386  			return
  1387  		}
  1388  		if o.AccountResolver == nil {
  1389  			err := &configErr{tk, "error parsing account resolver, should be MEM or " +
  1390  				" URL(\"url\") or a map containing dir and type state=[FULL|CACHE])"}
  1391  			*errors = append(*errors, err)
  1392  		}
  1393  	case "resolver_tls":
  1394  		tc, err := parseTLS(tk, true)
  1395  		if err != nil {
  1396  			*errors = append(*errors, err)
  1397  			return
  1398  		}
  1399  		tlsConfig, err := GenTLSConfig(tc)
  1400  		if err != nil {
  1401  			err := &configErr{tk, err.Error()}
  1402  			*errors = append(*errors, err)
  1403  			return
  1404  		}
  1405  		o.AccountResolverTLSConfig = tlsConfig
  1406  		// GenTLSConfig loads the CA file into ClientCAs, but since this will
  1407  		// be used as a client connection, we need to set RootCAs.
  1408  		o.AccountResolverTLSConfig.RootCAs = tlsConfig.ClientCAs
  1409  	case "resolver_preload":
  1410  		mp, ok := v.(map[string]interface{})
  1411  		if !ok {
  1412  			err := &configErr{tk, "preload should be a map of account_public_key:account_jwt"}
  1413  			*errors = append(*errors, err)
  1414  			return
  1415  		}
  1416  		o.resolverPreloads = make(map[string]string)
  1417  		for key, val := range mp {
  1418  			tk, val = unwrapValue(val, &lt)
  1419  			if jwtstr, ok := val.(string); !ok {
  1420  				*errors = append(*errors, &configErr{tk, "preload map value should be a string JWT"})
  1421  				continue
  1422  			} else {
  1423  				// Make sure this is a valid account JWT, that is a config error.
  1424  				// We will warn of expirations, etc later.
  1425  				if _, err := jwt.DecodeAccountClaims(jwtstr); err != nil {
  1426  					err := &configErr{tk, "invalid account JWT"}
  1427  					*errors = append(*errors, err)
  1428  					continue
  1429  				}
  1430  				o.resolverPreloads[key] = jwtstr
  1431  			}
  1432  		}
  1433  	case "resolver_pinned_accounts":
  1434  		switch v := v.(type) {
  1435  		case string:
  1436  			o.resolverPinnedAccounts = map[string]struct{}{v: {}}
  1437  		case []string:
  1438  			o.resolverPinnedAccounts = make(map[string]struct{})
  1439  			for _, mv := range v {
  1440  				o.resolverPinnedAccounts[mv] = struct{}{}
  1441  			}
  1442  		case []interface{}:
  1443  			o.resolverPinnedAccounts = make(map[string]struct{})
  1444  			for _, mv := range v {
  1445  				tk, mv = unwrapValue(mv, &lt)
  1446  				if key, ok := mv.(string); ok {
  1447  					o.resolverPinnedAccounts[key] = struct{}{}
  1448  				} else {
  1449  					err := &configErr{tk,
  1450  						fmt.Sprintf("error parsing resolver_pinned_accounts: unsupported type in array %T", mv)}
  1451  					*errors = append(*errors, err)
  1452  					continue
  1453  				}
  1454  			}
  1455  		default:
  1456  			err := &configErr{tk, fmt.Sprintf("error parsing resolver_pinned_accounts: unsupported type %T", v)}
  1457  			*errors = append(*errors, err)
  1458  			return
  1459  		}
  1460  	case "no_auth_user":
  1461  		o.NoAuthUser = v.(string)
  1462  	case "system_account", "system":
  1463  		// Already processed at the beginning so we just skip them
  1464  		// to not treat them as unknown values.
  1465  		return
  1466  	case "no_system_account", "no_system", "no_sys_acc":
  1467  		o.NoSystemAccount = v.(bool)
  1468  	case "no_header_support":
  1469  		o.NoHeaderSupport = v.(bool)
  1470  	case "trusted", "trusted_keys":
  1471  		switch v := v.(type) {
  1472  		case string:
  1473  			o.TrustedKeys = []string{v}
  1474  		case []string:
  1475  			o.TrustedKeys = v
  1476  		case []interface{}:
  1477  			keys := make([]string, 0, len(v))
  1478  			for _, mv := range v {
  1479  				tk, mv = unwrapValue(mv, &lt)
  1480  				if key, ok := mv.(string); ok {
  1481  					keys = append(keys, key)
  1482  				} else {
  1483  					err := &configErr{tk, fmt.Sprintf("error parsing trusted: unsupported type in array %T", mv)}
  1484  					*errors = append(*errors, err)
  1485  					continue
  1486  				}
  1487  			}
  1488  			o.TrustedKeys = keys
  1489  		default:
  1490  			err := &configErr{tk, fmt.Sprintf("error parsing trusted: unsupported type %T", v)}
  1491  			*errors = append(*errors, err)
  1492  		}
  1493  		// Do a quick sanity check on keys
  1494  		for _, key := range o.TrustedKeys {
  1495  			if !nkeys.IsValidPublicOperatorKey(key) {
  1496  				err := &configErr{tk, fmt.Sprintf("trust key %q required to be a valid public operator nkey", key)}
  1497  				*errors = append(*errors, err)
  1498  			}
  1499  		}
  1500  	case "connect_error_reports":
  1501  		o.ConnectErrorReports = int(v.(int64))
  1502  	case "reconnect_error_reports":
  1503  		o.ReconnectErrorReports = int(v.(int64))
  1504  	case "websocket", "ws":
  1505  		if err := parseWebsocket(tk, o, errors, warnings); err != nil {
  1506  			*errors = append(*errors, err)
  1507  			return
  1508  		}
  1509  	case "mqtt":
  1510  		if err := parseMQTT(tk, o, errors, warnings); err != nil {
  1511  			*errors = append(*errors, err)
  1512  			return
  1513  		}
  1514  	case "server_tags":
  1515  		var err error
  1516  		switch v := v.(type) {
  1517  		case string:
  1518  			o.Tags.Add(v)
  1519  		case []string:
  1520  			o.Tags.Add(v...)
  1521  		case []interface{}:
  1522  			for _, t := range v {
  1523  				if token, ok := t.(token); ok {
  1524  					if ts, ok := token.Value().(string); ok {
  1525  						o.Tags.Add(ts)
  1526  						continue
  1527  					} else {
  1528  						err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T where string is expected", token)}
  1529  					}
  1530  				} else {
  1531  					err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T", t)}
  1532  				}
  1533  				break
  1534  			}
  1535  		default:
  1536  			err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T", v)}
  1537  		}
  1538  		if err != nil {
  1539  			*errors = append(*errors, err)
  1540  			return
  1541  		}
  1542  	case "default_js_domain":
  1543  		vv, ok := v.(map[string]interface{})
  1544  		if !ok {
  1545  			*errors = append(*errors, &configErr{tk, fmt.Sprintf("error default_js_domain config: unsupported type %T", v)})
  1546  			return
  1547  		}
  1548  		m := make(map[string]string)
  1549  		for kk, kv := range vv {
  1550  			_, v = unwrapValue(kv, &tk)
  1551  			m[kk] = v.(string)
  1552  		}
  1553  		o.JsAccDefaultDomain = m
  1554  	case "ocsp_cache":
  1555  		var err error
  1556  		switch vv := v.(type) {
  1557  		case bool:
  1558  			pc := NewOCSPResponseCacheConfig()
  1559  			if vv {
  1560  				// Set enabled
  1561  				pc.Type = LOCAL
  1562  				o.OCSPCacheConfig = pc
  1563  			} else {
  1564  				// Set disabled (none cache)
  1565  				pc.Type = NONE
  1566  				o.OCSPCacheConfig = pc
  1567  			}
  1568  		case map[string]interface{}:
  1569  			pc, err := parseOCSPResponseCache(v)
  1570  			if err != nil {
  1571  				*errors = append(*errors, err)
  1572  				return
  1573  			}
  1574  			o.OCSPCacheConfig = pc
  1575  		default:
  1576  			err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T", v)}
  1577  		}
  1578  		if err != nil {
  1579  			*errors = append(*errors, err)
  1580  			return
  1581  		}
  1582  	default:
  1583  		if au := atomic.LoadInt32(&allowUnknownTopLevelField); au == 0 && !tk.IsUsedVariable() {
  1584  			err := &unknownConfigFieldErr{
  1585  				field: k,
  1586  				configErr: configErr{
  1587  					token: tk,
  1588  				},
  1589  			}
  1590  			*errors = append(*errors, err)
  1591  		}
  1592  	}
  1593  }
  1594  
  1595  func setupUsersAndNKeysDuplicateCheckMap(o *Options) map[string]struct{} {
  1596  	unames := make(map[string]struct{}, len(o.Users)+len(o.Nkeys))
  1597  	for _, u := range o.Users {
  1598  		unames[u.Username] = struct{}{}
  1599  	}
  1600  	for _, u := range o.Nkeys {
  1601  		unames[u.Nkey] = struct{}{}
  1602  	}
  1603  	return unames
  1604  }
  1605  
  1606  func parseDuration(field string, tk token, v interface{}, errors *[]error, warnings *[]error) time.Duration {
  1607  	if wd, ok := v.(string); ok {
  1608  		if dur, err := time.ParseDuration(wd); err != nil {
  1609  			err := &configErr{tk, fmt.Sprintf("error parsing %s: %v", field, err)}
  1610  			*errors = append(*errors, err)
  1611  			return 0
  1612  		} else {
  1613  			return dur
  1614  		}
  1615  	} else {
  1616  		// Backward compatible with old type, assume this is the
  1617  		// number of seconds.
  1618  		err := &configWarningErr{
  1619  			field: field,
  1620  			configErr: configErr{
  1621  				token:  tk,
  1622  				reason: field + " should be converted to a duration",
  1623  			},
  1624  		}
  1625  		*warnings = append(*warnings, err)
  1626  		return time.Duration(v.(int64)) * time.Second
  1627  	}
  1628  }
  1629  
  1630  func trackExplicitVal(opts *Options, pm *map[string]bool, name string, val bool) {
  1631  	m := *pm
  1632  	if m == nil {
  1633  		m = make(map[string]bool)
  1634  		*pm = m
  1635  	}
  1636  	m[name] = val
  1637  }
  1638  
  1639  // hostPort is simple struct to hold parsed listen/addr strings.
  1640  type hostPort struct {
  1641  	host string
  1642  	port int
  1643  }
  1644  
  1645  // parseListen will parse listen option which is replacing host/net and port
  1646  func parseListen(v interface{}) (*hostPort, error) {
  1647  	hp := &hostPort{}
  1648  	switch vv := v.(type) {
  1649  	// Only a port
  1650  	case int64:
  1651  		hp.port = int(vv)
  1652  	case string:
  1653  		host, port, err := net.SplitHostPort(vv)
  1654  		if err != nil {
  1655  			return nil, fmt.Errorf("could not parse address string %q", vv)
  1656  		}
  1657  		hp.port, err = strconv.Atoi(port)
  1658  		if err != nil {
  1659  			return nil, fmt.Errorf("could not parse port %q", port)
  1660  		}
  1661  		hp.host = host
  1662  	default:
  1663  		return nil, fmt.Errorf("expected port or host:port, got %T", vv)
  1664  	}
  1665  	return hp, nil
  1666  }
  1667  
  1668  // parseCluster will parse the cluster config.
  1669  func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]error) error {
  1670  	var lt token
  1671  	defer convertPanicToErrorList(&lt, errors)
  1672  
  1673  	tk, v := unwrapValue(v, &lt)
  1674  	cm, ok := v.(map[string]interface{})
  1675  	if !ok {
  1676  		return &configErr{tk, fmt.Sprintf("Expected map to define cluster, got %T", v)}
  1677  	}
  1678  
  1679  	for mk, mv := range cm {
  1680  		// Again, unwrap token value if line check is required.
  1681  		tk, mv = unwrapValue(mv, &lt)
  1682  		switch strings.ToLower(mk) {
  1683  		case "name":
  1684  			opts.Cluster.Name = mv.(string)
  1685  		case "listen":
  1686  			hp, err := parseListen(mv)
  1687  			if err != nil {
  1688  				err := &configErr{tk, err.Error()}
  1689  				*errors = append(*errors, err)
  1690  				continue
  1691  			}
  1692  			opts.Cluster.Host = hp.host
  1693  			opts.Cluster.Port = hp.port
  1694  		case "port":
  1695  			opts.Cluster.Port = int(mv.(int64))
  1696  		case "host", "net":
  1697  			opts.Cluster.Host = mv.(string)
  1698  		case "authorization":
  1699  			auth, err := parseAuthorization(tk, opts, errors, warnings)
  1700  			if err != nil {
  1701  				*errors = append(*errors, err)
  1702  				continue
  1703  			}
  1704  			if auth.users != nil {
  1705  				err := &configErr{tk, "Cluster authorization does not allow multiple users"}
  1706  				*errors = append(*errors, err)
  1707  				continue
  1708  			}
  1709  			if auth.token != _EMPTY_ {
  1710  				err := &configErr{tk, "Cluster authorization does not support tokens"}
  1711  				*errors = append(*errors, err)
  1712  				continue
  1713  			}
  1714  			if auth.callout != nil {
  1715  				err := &configErr{tk, "Cluster authorization does not support callouts"}
  1716  				*errors = append(*errors, err)
  1717  				continue
  1718  			}
  1719  
  1720  			opts.Cluster.Username = auth.user
  1721  			opts.Cluster.Password = auth.pass
  1722  			opts.Cluster.AuthTimeout = auth.timeout
  1723  
  1724  			if auth.defaultPermissions != nil {
  1725  				err := &configWarningErr{
  1726  					field: mk,
  1727  					configErr: configErr{
  1728  						token:  tk,
  1729  						reason: `setting "permissions" within cluster authorization block is deprecated`,
  1730  					},
  1731  				}
  1732  				*warnings = append(*warnings, err)
  1733  
  1734  				// Do not set permissions if they were specified in top-level cluster block.
  1735  				if opts.Cluster.Permissions == nil {
  1736  					setClusterPermissions(&opts.Cluster, auth.defaultPermissions)
  1737  				}
  1738  			}
  1739  		case "routes":
  1740  			ra := mv.([]interface{})
  1741  			routes, errs := parseURLs(ra, "route", warnings)
  1742  			if errs != nil {
  1743  				*errors = append(*errors, errs...)
  1744  				continue
  1745  			}
  1746  			opts.Routes = routes
  1747  		case "tls":
  1748  			config, tlsopts, err := getTLSConfig(tk)
  1749  			if err != nil {
  1750  				*errors = append(*errors, err)
  1751  				continue
  1752  			}
  1753  			opts.Cluster.TLSConfig = config
  1754  			opts.Cluster.TLSTimeout = tlsopts.Timeout
  1755  			opts.Cluster.TLSMap = tlsopts.Map
  1756  			opts.Cluster.TLSPinnedCerts = tlsopts.PinnedCerts
  1757  			opts.Cluster.TLSCheckKnownURLs = tlsopts.TLSCheckKnownURLs
  1758  			opts.Cluster.tlsConfigOpts = tlsopts
  1759  		case "cluster_advertise", "advertise":
  1760  			opts.Cluster.Advertise = mv.(string)
  1761  		case "no_advertise":
  1762  			opts.Cluster.NoAdvertise = mv.(bool)
  1763  			trackExplicitVal(opts, &opts.inConfig, "Cluster.NoAdvertise", opts.Cluster.NoAdvertise)
  1764  		case "connect_retries":
  1765  			opts.Cluster.ConnectRetries = int(mv.(int64))
  1766  		case "permissions":
  1767  			perms, err := parseUserPermissions(mv, errors, warnings)
  1768  			if err != nil {
  1769  				*errors = append(*errors, err)
  1770  				continue
  1771  			}
  1772  			// Dynamic response permissions do not make sense here.
  1773  			if perms.Response != nil {
  1774  				err := &configErr{tk, "Cluster permissions do not support dynamic responses"}
  1775  				*errors = append(*errors, err)
  1776  				continue
  1777  			}
  1778  			// This will possibly override permissions that were define in auth block
  1779  			setClusterPermissions(&opts.Cluster, perms)
  1780  		case "pool_size":
  1781  			opts.Cluster.PoolSize = int(mv.(int64))
  1782  		case "accounts":
  1783  			opts.Cluster.PinnedAccounts, _ = parseStringArray("accounts", tk, &lt, mv, errors, warnings)
  1784  		case "compression":
  1785  			if err := parseCompression(&opts.Cluster.Compression, CompressionS2Fast, tk, mk, mv); err != nil {
  1786  				*errors = append(*errors, err)
  1787  				continue
  1788  			}
  1789  		case "ping_interval":
  1790  			opts.Cluster.PingInterval = parseDuration("ping_interval", tk, mv, errors, warnings)
  1791  			if opts.Cluster.PingInterval > routeMaxPingInterval {
  1792  				*warnings = append(*warnings, &configErr{tk, fmt.Sprintf("Cluster 'ping_interval' will reset to %v which is the max for routes", routeMaxPingInterval)})
  1793  			}
  1794  		case "ping_max":
  1795  			opts.Cluster.MaxPingsOut = int(mv.(int64))
  1796  		default:
  1797  			if !tk.IsUsedVariable() {
  1798  				err := &unknownConfigFieldErr{
  1799  					field: mk,
  1800  					configErr: configErr{
  1801  						token: tk,
  1802  					},
  1803  				}
  1804  				*errors = append(*errors, err)
  1805  				continue
  1806  			}
  1807  		}
  1808  	}
  1809  	return nil
  1810  }
  1811  
  1812  // The parameter `chosenModeForOn` indicates which compression mode to use
  1813  // when the user selects "on" (or enabled, true, etc..). This is because
  1814  // we may have different defaults depending on where the compression is used.
  1815  func parseCompression(c *CompressionOpts, chosenModeForOn string, tk token, mk string, mv interface{}) (retErr error) {
  1816  	var lt token
  1817  	defer convertPanicToError(&lt, &retErr)
  1818  
  1819  	switch mv := mv.(type) {
  1820  	case string:
  1821  		// Do not validate here, it will be done in NewServer.
  1822  		c.Mode = mv
  1823  	case bool:
  1824  		if mv {
  1825  			c.Mode = chosenModeForOn
  1826  		} else {
  1827  			c.Mode = CompressionOff
  1828  		}
  1829  	case map[string]interface{}:
  1830  		for mk, mv := range mv {
  1831  			tk, mv = unwrapValue(mv, &lt)
  1832  			switch strings.ToLower(mk) {
  1833  			case "mode":
  1834  				c.Mode = mv.(string)
  1835  			case "rtt_thresholds", "thresholds", "rtts", "rtt":
  1836  				for _, iv := range mv.([]interface{}) {
  1837  					_, mv := unwrapValue(iv, &lt)
  1838  					dur, err := time.ParseDuration(mv.(string))
  1839  					if err != nil {
  1840  						return &configErr{tk, err.Error()}
  1841  					}
  1842  					c.RTTThresholds = append(c.RTTThresholds, dur)
  1843  				}
  1844  			default:
  1845  				if !tk.IsUsedVariable() {
  1846  					return &configErr{tk, fmt.Sprintf("unknown field %q", mk)}
  1847  				}
  1848  			}
  1849  		}
  1850  	default:
  1851  		return &configErr{tk, fmt.Sprintf("field %q should be a boolean or a structure, got %T", mk, mv)}
  1852  	}
  1853  	return nil
  1854  }
  1855  
  1856  func parseURLs(a []interface{}, typ string, warnings *[]error) (urls []*url.URL, errors []error) {
  1857  	urls = make([]*url.URL, 0, len(a))
  1858  	var lt token
  1859  	defer convertPanicToErrorList(&lt, &errors)
  1860  
  1861  	dd := make(map[string]bool)
  1862  
  1863  	for _, u := range a {
  1864  		tk, u := unwrapValue(u, &lt)
  1865  		sURL := u.(string)
  1866  		if dd[sURL] {
  1867  			err := &configWarningErr{
  1868  				field: sURL,
  1869  				configErr: configErr{
  1870  					token:  tk,
  1871  					reason: fmt.Sprintf("Duplicate %s entry detected", typ),
  1872  				},
  1873  			}
  1874  			*warnings = append(*warnings, err)
  1875  			continue
  1876  		}
  1877  		dd[sURL] = true
  1878  		url, err := parseURL(sURL, typ)
  1879  		if err != nil {
  1880  			err := &configErr{tk, err.Error()}
  1881  			errors = append(errors, err)
  1882  			continue
  1883  		}
  1884  		urls = append(urls, url)
  1885  	}
  1886  	return urls, errors
  1887  }
  1888  
  1889  func parseURL(u string, typ string) (*url.URL, error) {
  1890  	urlStr := strings.TrimSpace(u)
  1891  	url, err := url.Parse(urlStr)
  1892  	if err != nil {
  1893  		// Security note: if it's not well-formed but still reached us, then we're going to log as-is which might include password information here.
  1894  		// If the URL parses, we don't log the credentials ever, but if it doesn't even parse we don't have a sane way to redact.
  1895  		return nil, fmt.Errorf("error parsing %s url [%q]", typ, urlStr)
  1896  	}
  1897  	return url, nil
  1898  }
  1899  
  1900  func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) error {
  1901  	var lt token
  1902  	defer convertPanicToErrorList(&lt, errors)
  1903  
  1904  	tk, v := unwrapValue(v, &lt)
  1905  	gm, ok := v.(map[string]interface{})
  1906  	if !ok {
  1907  		return &configErr{tk, fmt.Sprintf("Expected gateway to be a map, got %T", v)}
  1908  	}
  1909  	for mk, mv := range gm {
  1910  		// Again, unwrap token value if line check is required.
  1911  		tk, mv = unwrapValue(mv, &lt)
  1912  		switch strings.ToLower(mk) {
  1913  		case "name":
  1914  			o.Gateway.Name = mv.(string)
  1915  		case "listen":
  1916  			hp, err := parseListen(mv)
  1917  			if err != nil {
  1918  				err := &configErr{tk, err.Error()}
  1919  				*errors = append(*errors, err)
  1920  				continue
  1921  			}
  1922  			o.Gateway.Host = hp.host
  1923  			o.Gateway.Port = hp.port
  1924  		case "port":
  1925  			o.Gateway.Port = int(mv.(int64))
  1926  		case "host", "net":
  1927  			o.Gateway.Host = mv.(string)
  1928  		case "authorization":
  1929  			auth, err := parseAuthorization(tk, o, errors, warnings)
  1930  			if err != nil {
  1931  				*errors = append(*errors, err)
  1932  				continue
  1933  			}
  1934  			if auth.users != nil {
  1935  				*errors = append(*errors, &configErr{tk, "Gateway authorization does not allow multiple users"})
  1936  				continue
  1937  			}
  1938  			if auth.token != _EMPTY_ {
  1939  				err := &configErr{tk, "Gateway authorization does not support tokens"}
  1940  				*errors = append(*errors, err)
  1941  				continue
  1942  			}
  1943  			if auth.callout != nil {
  1944  				err := &configErr{tk, "Gateway authorization does not support callouts"}
  1945  				*errors = append(*errors, err)
  1946  				continue
  1947  			}
  1948  
  1949  			o.Gateway.Username = auth.user
  1950  			o.Gateway.Password = auth.pass
  1951  			o.Gateway.AuthTimeout = auth.timeout
  1952  		case "tls":
  1953  			config, tlsopts, err := getTLSConfig(tk)
  1954  			if err != nil {
  1955  				*errors = append(*errors, err)
  1956  				continue
  1957  			}
  1958  			o.Gateway.TLSConfig = config
  1959  			o.Gateway.TLSTimeout = tlsopts.Timeout
  1960  			o.Gateway.TLSMap = tlsopts.Map
  1961  			o.Gateway.TLSCheckKnownURLs = tlsopts.TLSCheckKnownURLs
  1962  			o.Gateway.TLSPinnedCerts = tlsopts.PinnedCerts
  1963  			o.Gateway.tlsConfigOpts = tlsopts
  1964  		case "advertise":
  1965  			o.Gateway.Advertise = mv.(string)
  1966  		case "connect_retries":
  1967  			o.Gateway.ConnectRetries = int(mv.(int64))
  1968  		case "gateways":
  1969  			gateways, err := parseGateways(mv, errors, warnings)
  1970  			if err != nil {
  1971  				return err
  1972  			}
  1973  			o.Gateway.Gateways = gateways
  1974  		case "reject_unknown", "reject_unknown_cluster":
  1975  			o.Gateway.RejectUnknown = mv.(bool)
  1976  		default:
  1977  			if !tk.IsUsedVariable() {
  1978  				err := &unknownConfigFieldErr{
  1979  					field: mk,
  1980  					configErr: configErr{
  1981  						token: tk,
  1982  					},
  1983  				}
  1984  				*errors = append(*errors, err)
  1985  				continue
  1986  			}
  1987  		}
  1988  	}
  1989  	return nil
  1990  }
  1991  
  1992  var dynamicJSAccountLimits = JetStreamAccountLimits{-1, -1, -1, -1, -1, -1, -1, false}
  1993  var defaultJSAccountTiers = map[string]JetStreamAccountLimits{_EMPTY_: dynamicJSAccountLimits}
  1994  
  1995  // Parses jetstream account limits for an account. Simple setup with boolen is allowed, and we will
  1996  // use dynamic account limits.
  1997  func parseJetStreamForAccount(v interface{}, acc *Account, errors *[]error, warnings *[]error) error {
  1998  	var lt token
  1999  
  2000  	tk, v := unwrapValue(v, &lt)
  2001  
  2002  	// Value here can be bool, or string "enabled" or a map.
  2003  	switch vv := v.(type) {
  2004  	case bool:
  2005  		if vv {
  2006  			acc.jsLimits = defaultJSAccountTiers
  2007  		}
  2008  	case string:
  2009  		switch strings.ToLower(vv) {
  2010  		case "enabled", "enable":
  2011  			acc.jsLimits = defaultJSAccountTiers
  2012  		case "disabled", "disable":
  2013  			acc.jsLimits = nil
  2014  		default:
  2015  			return &configErr{tk, fmt.Sprintf("Expected 'enabled' or 'disabled' for string value, got '%s'", vv)}
  2016  		}
  2017  	case map[string]interface{}:
  2018  		jsLimits := JetStreamAccountLimits{-1, -1, -1, -1, -1, -1, -1, false}
  2019  		for mk, mv := range vv {
  2020  			tk, mv = unwrapValue(mv, &lt)
  2021  			switch strings.ToLower(mk) {
  2022  			case "max_memory", "max_mem", "mem", "memory":
  2023  				vv, ok := mv.(int64)
  2024  				if !ok {
  2025  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2026  				}
  2027  				jsLimits.MaxMemory = vv
  2028  			case "max_store", "max_file", "max_disk", "store", "disk":
  2029  				vv, ok := mv.(int64)
  2030  				if !ok {
  2031  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2032  				}
  2033  				jsLimits.MaxStore = vv
  2034  			case "max_streams", "streams":
  2035  				vv, ok := mv.(int64)
  2036  				if !ok {
  2037  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2038  				}
  2039  				jsLimits.MaxStreams = int(vv)
  2040  			case "max_consumers", "consumers":
  2041  				vv, ok := mv.(int64)
  2042  				if !ok {
  2043  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2044  				}
  2045  				jsLimits.MaxConsumers = int(vv)
  2046  			case "max_bytes_required", "max_stream_bytes", "max_bytes":
  2047  				vv, ok := mv.(bool)
  2048  				if !ok {
  2049  					return &configErr{tk, fmt.Sprintf("Expected a parseable bool for %q, got %v", mk, mv)}
  2050  				}
  2051  				jsLimits.MaxBytesRequired = vv
  2052  			case "mem_max_stream_bytes", "memory_max_stream_bytes":
  2053  				vv, ok := mv.(int64)
  2054  				if !ok {
  2055  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2056  				}
  2057  				jsLimits.MemoryMaxStreamBytes = vv
  2058  			case "disk_max_stream_bytes", "store_max_stream_bytes":
  2059  				vv, ok := mv.(int64)
  2060  				if !ok {
  2061  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2062  				}
  2063  				jsLimits.StoreMaxStreamBytes = vv
  2064  			case "max_ack_pending":
  2065  				vv, ok := mv.(int64)
  2066  				if !ok {
  2067  					return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)}
  2068  				}
  2069  				jsLimits.MaxAckPending = int(vv)
  2070  			default:
  2071  				if !tk.IsUsedVariable() {
  2072  					err := &unknownConfigFieldErr{
  2073  						field: mk,
  2074  						configErr: configErr{
  2075  							token: tk,
  2076  						},
  2077  					}
  2078  					*errors = append(*errors, err)
  2079  					continue
  2080  				}
  2081  			}
  2082  		}
  2083  		acc.jsLimits = map[string]JetStreamAccountLimits{_EMPTY_: jsLimits}
  2084  	default:
  2085  		return &configErr{tk, fmt.Sprintf("Expected map, bool or string to define JetStream, got %T", v)}
  2086  	}
  2087  	return nil
  2088  }
  2089  
  2090  // takes in a storage size as either an int or a string and returns an int64 value based on the input.
  2091  func getStorageSize(v interface{}) (int64, error) {
  2092  	_, ok := v.(int64)
  2093  	if ok {
  2094  		return v.(int64), nil
  2095  	}
  2096  
  2097  	s, ok := v.(string)
  2098  	if !ok {
  2099  		return 0, fmt.Errorf("must be int64 or string")
  2100  	}
  2101  
  2102  	if s == _EMPTY_ {
  2103  		return 0, nil
  2104  	}
  2105  
  2106  	suffix := s[len(s)-1:]
  2107  	prefix := s[:len(s)-1]
  2108  	num, err := strconv.ParseInt(prefix, 10, 64)
  2109  	if err != nil {
  2110  		return 0, err
  2111  	}
  2112  
  2113  	suffixMap := map[string]int64{"K": 10, "M": 20, "G": 30, "T": 40}
  2114  
  2115  	mult, ok := suffixMap[suffix]
  2116  	if !ok {
  2117  		return 0, fmt.Errorf("sizes defined as strings must end in K, M, G, T")
  2118  	}
  2119  	num *= 1 << mult
  2120  
  2121  	return num, nil
  2122  }
  2123  
  2124  // Parse enablement of jetstream for a server.
  2125  func parseJetStreamLimits(v interface{}, opts *Options, errors *[]error, warnings *[]error) error {
  2126  	var lt token
  2127  	tk, v := unwrapValue(v, &lt)
  2128  
  2129  	lim := JSLimitOpts{}
  2130  
  2131  	vv, ok := v.(map[string]interface{})
  2132  	if !ok {
  2133  		return &configErr{tk, fmt.Sprintf("Expected a map to define JetStreamLimits, got %T", v)}
  2134  	}
  2135  	for mk, mv := range vv {
  2136  		tk, mv = unwrapValue(mv, &lt)
  2137  		switch strings.ToLower(mk) {
  2138  		case "max_ack_pending":
  2139  			lim.MaxAckPending = int(mv.(int64))
  2140  		case "max_ha_assets":
  2141  			lim.MaxHAAssets = int(mv.(int64))
  2142  		case "max_request_batch":
  2143  			lim.MaxRequestBatch = int(mv.(int64))
  2144  		case "duplicate_window":
  2145  			var err error
  2146  			lim.Duplicates, err = time.ParseDuration(mv.(string))
  2147  			if err != nil {
  2148  				*errors = append(*errors, err)
  2149  			}
  2150  		default:
  2151  			if !tk.IsUsedVariable() {
  2152  				err := &unknownConfigFieldErr{
  2153  					field: mk,
  2154  					configErr: configErr{
  2155  						token: tk,
  2156  					},
  2157  				}
  2158  				*errors = append(*errors, err)
  2159  				continue
  2160  			}
  2161  		}
  2162  	}
  2163  	opts.JetStreamLimits = lim
  2164  	return nil
  2165  }
  2166  
  2167  // Parse enablement of jetstream for a server.
  2168  func parseJetStream(v interface{}, opts *Options, errors *[]error, warnings *[]error) error {
  2169  	var lt token
  2170  
  2171  	tk, v := unwrapValue(v, &lt)
  2172  
  2173  	// Value here can be bool, or string "enabled" or a map.
  2174  	switch vv := v.(type) {
  2175  	case bool:
  2176  		opts.JetStream = v.(bool)
  2177  	case string:
  2178  		switch strings.ToLower(vv) {
  2179  		case "enabled", "enable":
  2180  			opts.JetStream = true
  2181  		case "disabled", "disable":
  2182  			opts.JetStream = false
  2183  		default:
  2184  			return &configErr{tk, fmt.Sprintf("Expected 'enabled' or 'disabled' for string value, got '%s'", vv)}
  2185  		}
  2186  	case map[string]interface{}:
  2187  		doEnable := true
  2188  		for mk, mv := range vv {
  2189  			tk, mv = unwrapValue(mv, &lt)
  2190  			switch strings.ToLower(mk) {
  2191  			case "store", "store_dir", "storedir":
  2192  				// StoreDir can be set at the top level as well so have to prevent ambiguous declarations.
  2193  				if opts.StoreDir != _EMPTY_ {
  2194  					return &configErr{tk, "Duplicate 'store_dir' configuration"}
  2195  				}
  2196  				opts.StoreDir = mv.(string)
  2197  			case "sync", "sync_interval":
  2198  				if v, ok := mv.(string); ok && strings.ToLower(v) == "always" {
  2199  					opts.SyncInterval = defaultSyncInterval
  2200  					opts.SyncAlways = true
  2201  				} else {
  2202  					opts.SyncInterval = parseDuration(mk, tk, mv, errors, warnings)
  2203  				}
  2204  				opts.syncSet = true
  2205  			case "max_memory_store", "max_mem_store", "max_mem":
  2206  				s, err := getStorageSize(mv)
  2207  				if err != nil {
  2208  					return &configErr{tk, fmt.Sprintf("max_mem_store %s", err)}
  2209  				}
  2210  				opts.JetStreamMaxMemory = s
  2211  				opts.maxMemSet = true
  2212  			case "max_file_store", "max_file":
  2213  				s, err := getStorageSize(mv)
  2214  				if err != nil {
  2215  					return &configErr{tk, fmt.Sprintf("max_file_store %s", err)}
  2216  				}
  2217  				opts.JetStreamMaxStore = s
  2218  				opts.maxStoreSet = true
  2219  			case "domain":
  2220  				opts.JetStreamDomain = mv.(string)
  2221  			case "enable", "enabled":
  2222  				doEnable = mv.(bool)
  2223  			case "key", "ek", "encryption_key":
  2224  				opts.JetStreamKey = mv.(string)
  2225  			case "prev_key", "prev_ek", "prev_encryption_key":
  2226  				opts.JetStreamOldKey = mv.(string)
  2227  			case "cipher":
  2228  				switch strings.ToLower(mv.(string)) {
  2229  				case "chacha", "chachapoly":
  2230  					opts.JetStreamCipher = ChaCha
  2231  				case "aes":
  2232  					opts.JetStreamCipher = AES
  2233  				default:
  2234  					return &configErr{tk, fmt.Sprintf("Unknown cipher type: %q", mv)}
  2235  				}
  2236  			case "extension_hint":
  2237  				opts.JetStreamExtHint = mv.(string)
  2238  			case "limits":
  2239  				if err := parseJetStreamLimits(tk, opts, errors, warnings); err != nil {
  2240  					return err
  2241  				}
  2242  			case "unique_tag":
  2243  				opts.JetStreamUniqueTag = strings.ToLower(strings.TrimSpace(mv.(string)))
  2244  			case "max_outstanding_catchup":
  2245  				s, err := getStorageSize(mv)
  2246  				if err != nil {
  2247  					return &configErr{tk, fmt.Sprintf("%s %s", strings.ToLower(mk), err)}
  2248  				}
  2249  				opts.JetStreamMaxCatchup = s
  2250  			default:
  2251  				if !tk.IsUsedVariable() {
  2252  					err := &unknownConfigFieldErr{
  2253  						field: mk,
  2254  						configErr: configErr{
  2255  							token: tk,
  2256  						},
  2257  					}
  2258  					*errors = append(*errors, err)
  2259  					continue
  2260  				}
  2261  			}
  2262  		}
  2263  		opts.JetStream = doEnable
  2264  	default:
  2265  		return &configErr{tk, fmt.Sprintf("Expected map, bool or string to define JetStream, got %T", v)}
  2266  	}
  2267  
  2268  	return nil
  2269  }
  2270  
  2271  // parseLeafNodes will parse the leaf node config.
  2272  func parseLeafNodes(v interface{}, opts *Options, errors *[]error, warnings *[]error) error {
  2273  	var lt token
  2274  	defer convertPanicToErrorList(&lt, errors)
  2275  
  2276  	tk, v := unwrapValue(v, &lt)
  2277  	cm, ok := v.(map[string]interface{})
  2278  	if !ok {
  2279  		return &configErr{tk, fmt.Sprintf("Expected map to define a leafnode, got %T", v)}
  2280  	}
  2281  
  2282  	for mk, mv := range cm {
  2283  		// Again, unwrap token value if line check is required.
  2284  		tk, mv = unwrapValue(mv, &lt)
  2285  		switch strings.ToLower(mk) {
  2286  		case "listen":
  2287  			hp, err := parseListen(mv)
  2288  			if err != nil {
  2289  				err := &configErr{tk, err.Error()}
  2290  				*errors = append(*errors, err)
  2291  				continue
  2292  			}
  2293  			opts.LeafNode.Host = hp.host
  2294  			opts.LeafNode.Port = hp.port
  2295  		case "port":
  2296  			opts.LeafNode.Port = int(mv.(int64))
  2297  		case "host", "net":
  2298  			opts.LeafNode.Host = mv.(string)
  2299  		case "authorization":
  2300  			auth, err := parseLeafAuthorization(tk, errors, warnings)
  2301  			if err != nil {
  2302  				*errors = append(*errors, err)
  2303  				continue
  2304  			}
  2305  			opts.LeafNode.Username = auth.user
  2306  			opts.LeafNode.Password = auth.pass
  2307  			opts.LeafNode.AuthTimeout = auth.timeout
  2308  			opts.LeafNode.Account = auth.acc
  2309  			opts.LeafNode.Users = auth.users
  2310  			opts.LeafNode.Nkey = auth.nkey
  2311  			// Validate user info config for leafnode authorization
  2312  			if err := validateLeafNodeAuthOptions(opts); err != nil {
  2313  				*errors = append(*errors, &configErr{tk, err.Error()})
  2314  				continue
  2315  			}
  2316  		case "remotes":
  2317  			// Parse the remote options here.
  2318  			remotes, err := parseRemoteLeafNodes(tk, errors, warnings)
  2319  			if err != nil {
  2320  				*errors = append(*errors, err)
  2321  				continue
  2322  			}
  2323  			opts.LeafNode.Remotes = remotes
  2324  		case "reconnect", "reconnect_delay", "reconnect_interval":
  2325  			opts.LeafNode.ReconnectInterval = parseDuration("reconnect", tk, mv, errors, warnings)
  2326  		case "tls":
  2327  			tc, err := parseTLS(tk, true)
  2328  			if err != nil {
  2329  				*errors = append(*errors, err)
  2330  				continue
  2331  			}
  2332  			if opts.LeafNode.TLSConfig, err = GenTLSConfig(tc); err != nil {
  2333  				err := &configErr{tk, err.Error()}
  2334  				*errors = append(*errors, err)
  2335  				continue
  2336  			}
  2337  			opts.LeafNode.TLSTimeout = tc.Timeout
  2338  			opts.LeafNode.TLSMap = tc.Map
  2339  			opts.LeafNode.TLSPinnedCerts = tc.PinnedCerts
  2340  			opts.LeafNode.TLSHandshakeFirst = tc.HandshakeFirst
  2341  			opts.LeafNode.tlsConfigOpts = tc
  2342  		case "leafnode_advertise", "advertise":
  2343  			opts.LeafNode.Advertise = mv.(string)
  2344  		case "no_advertise":
  2345  			opts.LeafNode.NoAdvertise = mv.(bool)
  2346  			trackExplicitVal(opts, &opts.inConfig, "LeafNode.NoAdvertise", opts.LeafNode.NoAdvertise)
  2347  		case "min_version", "minimum_version":
  2348  			version := mv.(string)
  2349  			if err := checkLeafMinVersionConfig(version); err != nil {
  2350  				err = &configErr{tk, err.Error()}
  2351  				*errors = append(*errors, err)
  2352  				continue
  2353  			}
  2354  			opts.LeafNode.MinVersion = version
  2355  		case "compression":
  2356  			if err := parseCompression(&opts.LeafNode.Compression, CompressionS2Auto, tk, mk, mv); err != nil {
  2357  				*errors = append(*errors, err)
  2358  				continue
  2359  			}
  2360  		default:
  2361  			if !tk.IsUsedVariable() {
  2362  				err := &unknownConfigFieldErr{
  2363  					field: mk,
  2364  					configErr: configErr{
  2365  						token: tk,
  2366  					},
  2367  				}
  2368  				*errors = append(*errors, err)
  2369  				continue
  2370  			}
  2371  		}
  2372  	}
  2373  	return nil
  2374  }
  2375  
  2376  // This is the authorization parser adapter for the leafnode's
  2377  // authorization config.
  2378  func parseLeafAuthorization(v interface{}, errors *[]error, warnings *[]error) (*authorization, error) {
  2379  	var (
  2380  		am   map[string]interface{}
  2381  		tk   token
  2382  		lt   token
  2383  		auth = &authorization{}
  2384  	)
  2385  	defer convertPanicToErrorList(&lt, errors)
  2386  
  2387  	_, v = unwrapValue(v, &lt)
  2388  	am = v.(map[string]interface{})
  2389  	for mk, mv := range am {
  2390  		tk, mv = unwrapValue(mv, &lt)
  2391  		switch strings.ToLower(mk) {
  2392  		case "user", "username":
  2393  			auth.user = mv.(string)
  2394  		case "pass", "password":
  2395  			auth.pass = mv.(string)
  2396  		case "nkey":
  2397  			nk := mv.(string)
  2398  			if !nkeys.IsValidPublicUserKey(nk) {
  2399  				*errors = append(*errors, &configErr{tk, "Not a valid public nkey for leafnode authorization"})
  2400  			}
  2401  			auth.nkey = nk
  2402  		case "timeout":
  2403  			at := float64(1)
  2404  			switch mv := mv.(type) {
  2405  			case int64:
  2406  				at = float64(mv)
  2407  			case float64:
  2408  				at = mv
  2409  			}
  2410  			auth.timeout = at
  2411  		case "users":
  2412  			users, err := parseLeafUsers(tk, errors, warnings)
  2413  			if err != nil {
  2414  				*errors = append(*errors, err)
  2415  				continue
  2416  			}
  2417  			auth.users = users
  2418  		case "account":
  2419  			auth.acc = mv.(string)
  2420  		default:
  2421  			if !tk.IsUsedVariable() {
  2422  				err := &unknownConfigFieldErr{
  2423  					field: mk,
  2424  					configErr: configErr{
  2425  						token: tk,
  2426  					},
  2427  				}
  2428  				*errors = append(*errors, err)
  2429  			}
  2430  			continue
  2431  		}
  2432  	}
  2433  	return auth, nil
  2434  }
  2435  
  2436  // This is a trimmed down version of parseUsers that is adapted
  2437  // for the users possibly defined in the authorization{} section
  2438  // of leafnodes {}.
  2439  func parseLeafUsers(mv interface{}, errors *[]error, warnings *[]error) ([]*User, error) {
  2440  	var (
  2441  		tk    token
  2442  		lt    token
  2443  		users = []*User{}
  2444  	)
  2445  	defer convertPanicToErrorList(&lt, errors)
  2446  
  2447  	tk, mv = unwrapValue(mv, &lt)
  2448  	// Make sure we have an array
  2449  	uv, ok := mv.([]interface{})
  2450  	if !ok {
  2451  		return nil, &configErr{tk, fmt.Sprintf("Expected users field to be an array, got %v", mv)}
  2452  	}
  2453  	for _, u := range uv {
  2454  		tk, u = unwrapValue(u, &lt)
  2455  		// Check its a map/struct
  2456  		um, ok := u.(map[string]interface{})
  2457  		if !ok {
  2458  			err := &configErr{tk, fmt.Sprintf("Expected user entry to be a map/struct, got %v", u)}
  2459  			*errors = append(*errors, err)
  2460  			continue
  2461  		}
  2462  		user := &User{}
  2463  		for k, v := range um {
  2464  			tk, v = unwrapValue(v, &lt)
  2465  			switch strings.ToLower(k) {
  2466  			case "user", "username":
  2467  				user.Username = v.(string)
  2468  			case "pass", "password":
  2469  				user.Password = v.(string)
  2470  			case "account":
  2471  				// We really want to save just the account name here, but
  2472  				// the User object is *Account. So we create an account object
  2473  				// but it won't be registered anywhere. The server will just
  2474  				// use opts.LeafNode.Users[].Account.Name. Alternatively
  2475  				// we need to create internal objects to store u/p and account
  2476  				// name and have a server structure to hold that.
  2477  				user.Account = NewAccount(v.(string))
  2478  			default:
  2479  				if !tk.IsUsedVariable() {
  2480  					err := &unknownConfigFieldErr{
  2481  						field: k,
  2482  						configErr: configErr{
  2483  							token: tk,
  2484  						},
  2485  					}
  2486  					*errors = append(*errors, err)
  2487  					continue
  2488  				}
  2489  			}
  2490  		}
  2491  		users = append(users, user)
  2492  	}
  2493  	return users, nil
  2494  }
  2495  
  2496  func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([]*RemoteLeafOpts, error) {
  2497  	var lt token
  2498  	defer convertPanicToErrorList(&lt, errors)
  2499  	tk, v := unwrapValue(v, &lt)
  2500  	ra, ok := v.([]interface{})
  2501  	if !ok {
  2502  		return nil, &configErr{tk, fmt.Sprintf("Expected remotes field to be an array, got %T", v)}
  2503  	}
  2504  	remotes := make([]*RemoteLeafOpts, 0, len(ra))
  2505  	for _, r := range ra {
  2506  		tk, r = unwrapValue(r, &lt)
  2507  		// Check its a map/struct
  2508  		rm, ok := r.(map[string]interface{})
  2509  		if !ok {
  2510  			*errors = append(*errors, &configErr{tk, fmt.Sprintf("Expected remote leafnode entry to be a map/struct, got %v", r)})
  2511  			continue
  2512  		}
  2513  		remote := &RemoteLeafOpts{}
  2514  		for k, v := range rm {
  2515  			tk, v = unwrapValue(v, &lt)
  2516  			switch strings.ToLower(k) {
  2517  			case "no_randomize", "dont_randomize":
  2518  				remote.NoRandomize = v.(bool)
  2519  			case "url", "urls":
  2520  				switch v := v.(type) {
  2521  				case []interface{}, []string:
  2522  					urls, errs := parseURLs(v.([]interface{}), "leafnode", warnings)
  2523  					if errs != nil {
  2524  						*errors = append(*errors, errs...)
  2525  						continue
  2526  					}
  2527  					remote.URLs = urls
  2528  				case string:
  2529  					url, err := parseURL(v, "leafnode")
  2530  					if err != nil {
  2531  						*errors = append(*errors, &configErr{tk, err.Error()})
  2532  						continue
  2533  					}
  2534  					remote.URLs = append(remote.URLs, url)
  2535  				default:
  2536  					*errors = append(*errors, &configErr{tk, fmt.Sprintf("Expected remote leafnode url to be an array or string, got %v", v)})
  2537  					continue
  2538  				}
  2539  			case "account", "local":
  2540  				remote.LocalAccount = v.(string)
  2541  			case "creds", "credentials":
  2542  				p, err := expandPath(v.(string))
  2543  				if err != nil {
  2544  					*errors = append(*errors, &configErr{tk, err.Error()})
  2545  					continue
  2546  				}
  2547  				// Can't have both creds and nkey
  2548  				if remote.Nkey != _EMPTY_ {
  2549  					*errors = append(*errors, &configErr{tk, "Remote leafnode can not have both creds and nkey defined"})
  2550  					continue
  2551  				}
  2552  				remote.Credentials = p
  2553  			case "nkey", "seed":
  2554  				nk := v.(string)
  2555  				if pb, _, err := nkeys.DecodeSeed([]byte(nk)); err != nil || pb != nkeys.PrefixByteUser {
  2556  					err := &configErr{tk, fmt.Sprintf("Remote leafnode nkey is not a valid seed: %q", v)}
  2557  					*errors = append(*errors, err)
  2558  					continue
  2559  				}
  2560  				if remote.Credentials != _EMPTY_ {
  2561  					*errors = append(*errors, &configErr{tk, "Remote leafnode can not have both creds and nkey defined"})
  2562  					continue
  2563  				}
  2564  				remote.Nkey = nk
  2565  			case "tls":
  2566  				tc, err := parseTLS(tk, true)
  2567  				if err != nil {
  2568  					*errors = append(*errors, err)
  2569  					continue
  2570  				}
  2571  				if remote.TLSConfig, err = GenTLSConfig(tc); err != nil {
  2572  					*errors = append(*errors, &configErr{tk, err.Error()})
  2573  					continue
  2574  				}
  2575  				// If ca_file is defined, GenTLSConfig() sets TLSConfig.ClientCAs.
  2576  				// Set RootCAs since this tls.Config is used when soliciting
  2577  				// a connection (therefore behaves as a client).
  2578  				remote.TLSConfig.RootCAs = remote.TLSConfig.ClientCAs
  2579  				if tc.Timeout > 0 {
  2580  					remote.TLSTimeout = tc.Timeout
  2581  				} else {
  2582  					remote.TLSTimeout = float64(DEFAULT_LEAF_TLS_TIMEOUT) / float64(time.Second)
  2583  				}
  2584  				remote.TLSHandshakeFirst = tc.HandshakeFirst
  2585  				remote.tlsConfigOpts = tc
  2586  			case "hub":
  2587  				remote.Hub = v.(bool)
  2588  			case "deny_imports", "deny_import":
  2589  				subjects, err := parsePermSubjects(tk, errors, warnings)
  2590  				if err != nil {
  2591  					*errors = append(*errors, err)
  2592  					continue
  2593  				}
  2594  				remote.DenyImports = subjects
  2595  			case "deny_exports", "deny_export":
  2596  				subjects, err := parsePermSubjects(tk, errors, warnings)
  2597  				if err != nil {
  2598  					*errors = append(*errors, err)
  2599  					continue
  2600  				}
  2601  				remote.DenyExports = subjects
  2602  			case "ws_compress", "ws_compression", "websocket_compress", "websocket_compression":
  2603  				remote.Websocket.Compression = v.(bool)
  2604  			case "ws_no_masking", "websocket_no_masking":
  2605  				remote.Websocket.NoMasking = v.(bool)
  2606  			case "jetstream_cluster_migrate", "js_cluster_migrate":
  2607  				remote.JetStreamClusterMigrate = true
  2608  			case "compression":
  2609  				if err := parseCompression(&remote.Compression, CompressionS2Auto, tk, k, v); err != nil {
  2610  					*errors = append(*errors, err)
  2611  					continue
  2612  				}
  2613  			default:
  2614  				if !tk.IsUsedVariable() {
  2615  					err := &unknownConfigFieldErr{
  2616  						field: k,
  2617  						configErr: configErr{
  2618  							token: tk,
  2619  						},
  2620  					}
  2621  					*errors = append(*errors, err)
  2622  					continue
  2623  				}
  2624  			}
  2625  		}
  2626  		remotes = append(remotes, remote)
  2627  	}
  2628  	return remotes, nil
  2629  }
  2630  
  2631  // Parse TLS and returns a TLSConfig and TLSTimeout.
  2632  // Used by cluster and gateway parsing.
  2633  func getTLSConfig(tk token) (*tls.Config, *TLSConfigOpts, error) {
  2634  	tc, err := parseTLS(tk, false)
  2635  	if err != nil {
  2636  		return nil, nil, err
  2637  	}
  2638  	config, err := GenTLSConfig(tc)
  2639  	if err != nil {
  2640  		err := &configErr{tk, err.Error()}
  2641  		return nil, nil, err
  2642  	}
  2643  	// For clusters/gateways, we will force strict verification. We also act
  2644  	// as both client and server, so will mirror the rootCA to the
  2645  	// clientCA pool.
  2646  	config.ClientAuth = tls.RequireAndVerifyClientCert
  2647  	config.RootCAs = config.ClientCAs
  2648  	return config, tc, nil
  2649  }
  2650  
  2651  func parseGateways(v interface{}, errors *[]error, warnings *[]error) ([]*RemoteGatewayOpts, error) {
  2652  	var lt token
  2653  	defer convertPanicToErrorList(&lt, errors)
  2654  
  2655  	tk, v := unwrapValue(v, &lt)
  2656  	// Make sure we have an array
  2657  	ga, ok := v.([]interface{})
  2658  	if !ok {
  2659  		return nil, &configErr{tk, fmt.Sprintf("Expected gateways field to be an array, got %T", v)}
  2660  	}
  2661  	gateways := []*RemoteGatewayOpts{}
  2662  	for _, g := range ga {
  2663  		tk, g = unwrapValue(g, &lt)
  2664  		// Check its a map/struct
  2665  		gm, ok := g.(map[string]interface{})
  2666  		if !ok {
  2667  			*errors = append(*errors, &configErr{tk, fmt.Sprintf("Expected gateway entry to be a map/struct, got %v", g)})
  2668  			continue
  2669  		}
  2670  		gateway := &RemoteGatewayOpts{}
  2671  		for k, v := range gm {
  2672  			tk, v = unwrapValue(v, &lt)
  2673  			switch strings.ToLower(k) {
  2674  			case "name":
  2675  				gateway.Name = v.(string)
  2676  			case "tls":
  2677  				tls, tlsopts, err := getTLSConfig(tk)
  2678  				if err != nil {
  2679  					*errors = append(*errors, err)
  2680  					continue
  2681  				}
  2682  				gateway.TLSConfig = tls
  2683  				gateway.TLSTimeout = tlsopts.Timeout
  2684  				gateway.tlsConfigOpts = tlsopts
  2685  			case "url":
  2686  				url, err := parseURL(v.(string), "gateway")
  2687  				if err != nil {
  2688  					*errors = append(*errors, &configErr{tk, err.Error()})
  2689  					continue
  2690  				}
  2691  				gateway.URLs = append(gateway.URLs, url)
  2692  			case "urls":
  2693  				urls, errs := parseURLs(v.([]interface{}), "gateway", warnings)
  2694  				if errs != nil {
  2695  					*errors = append(*errors, errs...)
  2696  					continue
  2697  				}
  2698  				gateway.URLs = urls
  2699  			default:
  2700  				if !tk.IsUsedVariable() {
  2701  					err := &unknownConfigFieldErr{
  2702  						field: k,
  2703  						configErr: configErr{
  2704  							token: tk,
  2705  						},
  2706  					}
  2707  					*errors = append(*errors, err)
  2708  					continue
  2709  				}
  2710  			}
  2711  		}
  2712  		gateways = append(gateways, gateway)
  2713  	}
  2714  	return gateways, nil
  2715  }
  2716  
  2717  // Sets cluster's permissions based on given pub/sub permissions,
  2718  // doing the appropriate translation.
  2719  func setClusterPermissions(opts *ClusterOpts, perms *Permissions) {
  2720  	// Import is whether or not we will send a SUB for interest to the other side.
  2721  	// Export is whether or not we will accept a SUB from the remote for a given subject.
  2722  	// Both only effect interest registration.
  2723  	// The parsing sets Import into Publish and Export into Subscribe, convert
  2724  	// accordingly.
  2725  	opts.Permissions = &RoutePermissions{
  2726  		Import: perms.Publish,
  2727  		Export: perms.Subscribe,
  2728  	}
  2729  }
  2730  
  2731  // Temp structures to hold account import and export defintions since they need
  2732  // to be processed after being parsed.
  2733  type export struct {
  2734  	acc  *Account
  2735  	sub  string
  2736  	accs []string
  2737  	rt   ServiceRespType
  2738  	lat  *serviceLatency
  2739  	rthr time.Duration
  2740  	tPos uint
  2741  	atrc bool // allow_trace
  2742  }
  2743  
  2744  type importStream struct {
  2745  	acc  *Account
  2746  	an   string
  2747  	sub  string
  2748  	to   string
  2749  	pre  string
  2750  	atrc bool // allow_trace
  2751  }
  2752  
  2753  type importService struct {
  2754  	acc   *Account
  2755  	an    string
  2756  	sub   string
  2757  	to    string
  2758  	share bool
  2759  }
  2760  
  2761  // Checks if an account name is reserved.
  2762  func isReservedAccount(name string) bool {
  2763  	return name == globalAccountName
  2764  }
  2765  
  2766  func parseAccountMapDest(v interface{}, tk token, errors *[]error, warnings *[]error) (*MapDest, *configErr) {
  2767  	// These should be maps.
  2768  	mv, ok := v.(map[string]interface{})
  2769  	if !ok {
  2770  		err := &configErr{tk, "Expected an entry for the mapping destination"}
  2771  		*errors = append(*errors, err)
  2772  		return nil, err
  2773  	}
  2774  
  2775  	mdest := &MapDest{}
  2776  	var lt token
  2777  	var sw bool
  2778  
  2779  	for k, v := range mv {
  2780  		tk, dmv := unwrapValue(v, &lt)
  2781  		switch strings.ToLower(k) {
  2782  		case "dest", "destination":
  2783  			mdest.Subject = dmv.(string)
  2784  		case "weight":
  2785  			switch vv := dmv.(type) {
  2786  			case string:
  2787  				ws := vv
  2788  				ws = strings.TrimSuffix(ws, "%")
  2789  				weight, err := strconv.Atoi(ws)
  2790  				if err != nil {
  2791  					err := &configErr{tk, fmt.Sprintf("Invalid weight %q for mapping destination", ws)}
  2792  					*errors = append(*errors, err)
  2793  					return nil, err
  2794  				}
  2795  				if weight > 100 || weight < 0 {
  2796  					err := &configErr{tk, fmt.Sprintf("Invalid weight %d for mapping destination", weight)}
  2797  					*errors = append(*errors, err)
  2798  					return nil, err
  2799  				}
  2800  				mdest.Weight = uint8(weight)
  2801  				sw = true
  2802  			case int64:
  2803  				weight := vv
  2804  				if weight > 100 || weight < 0 {
  2805  					err := &configErr{tk, fmt.Sprintf("Invalid weight %d for mapping destination", weight)}
  2806  					*errors = append(*errors, err)
  2807  					return nil, err
  2808  				}
  2809  				mdest.Weight = uint8(weight)
  2810  				sw = true
  2811  			default:
  2812  				err := &configErr{tk, fmt.Sprintf("Unknown entry type for weight of %v\n", vv)}
  2813  				*errors = append(*errors, err)
  2814  				return nil, err
  2815  			}
  2816  		case "cluster":
  2817  			mdest.Cluster = dmv.(string)
  2818  		default:
  2819  			err := &configErr{tk, fmt.Sprintf("Unknown field %q for mapping destination", k)}
  2820  			*errors = append(*errors, err)
  2821  			return nil, err
  2822  		}
  2823  	}
  2824  
  2825  	if !sw {
  2826  		err := &configErr{tk, fmt.Sprintf("Missing weight for mapping destination %q", mdest.Subject)}
  2827  		*errors = append(*errors, err)
  2828  		return nil, err
  2829  	}
  2830  
  2831  	return mdest, nil
  2832  }
  2833  
  2834  // parseAccountMappings is called to parse account mappings.
  2835  func parseAccountMappings(v interface{}, acc *Account, errors *[]error, warnings *[]error) error {
  2836  	var lt token
  2837  	defer convertPanicToErrorList(&lt, errors)
  2838  
  2839  	tk, v := unwrapValue(v, &lt)
  2840  	am := v.(map[string]interface{})
  2841  	for subj, mv := range am {
  2842  		if !IsValidSubject(subj) {
  2843  			err := &configErr{tk, fmt.Sprintf("Subject %q is not a valid subject", subj)}
  2844  			*errors = append(*errors, err)
  2845  			continue
  2846  		}
  2847  		tk, v := unwrapValue(mv, &lt)
  2848  
  2849  		switch vv := v.(type) {
  2850  		case string:
  2851  			if err := acc.AddMapping(subj, v.(string)); err != nil {
  2852  				err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q to %q : %v", subj, v.(string), err)}
  2853  				*errors = append(*errors, err)
  2854  				continue
  2855  			}
  2856  		case []interface{}:
  2857  			var mappings []*MapDest
  2858  			for _, mv := range v.([]interface{}) {
  2859  				tk, amv := unwrapValue(mv, &lt)
  2860  				mdest, err := parseAccountMapDest(amv, tk, errors, warnings)
  2861  				if err != nil {
  2862  					continue
  2863  				}
  2864  				mappings = append(mappings, mdest)
  2865  			}
  2866  
  2867  			// Now add them in..
  2868  			if err := acc.AddWeightedMappings(subj, mappings...); err != nil {
  2869  				err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q : %v", subj, err)}
  2870  				*errors = append(*errors, err)
  2871  				continue
  2872  			}
  2873  		case interface{}:
  2874  			tk, amv := unwrapValue(mv, &lt)
  2875  			mdest, err := parseAccountMapDest(amv, tk, errors, warnings)
  2876  			if err != nil {
  2877  				continue
  2878  			}
  2879  			// Now add it in..
  2880  			if err := acc.AddWeightedMappings(subj, mdest); err != nil {
  2881  				err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q : %v", subj, err)}
  2882  				*errors = append(*errors, err)
  2883  				continue
  2884  			}
  2885  		default:
  2886  			err := &configErr{tk, fmt.Sprintf("Unknown type %T for mapping destination", vv)}
  2887  			*errors = append(*errors, err)
  2888  			continue
  2889  		}
  2890  	}
  2891  
  2892  	return nil
  2893  }
  2894  
  2895  // parseAccountLimits is called to parse account limits in a server config.
  2896  func parseAccountLimits(mv interface{}, acc *Account, errors *[]error, warnings *[]error) error {
  2897  	var lt token
  2898  	defer convertPanicToErrorList(&lt, errors)
  2899  
  2900  	tk, v := unwrapValue(mv, &lt)
  2901  	am, ok := v.(map[string]interface{})
  2902  	if !ok {
  2903  		return &configErr{tk, fmt.Sprintf("Expected account limits to be a map/struct, got %+v", v)}
  2904  	}
  2905  
  2906  	for k, v := range am {
  2907  		tk, mv = unwrapValue(v, &lt)
  2908  		switch strings.ToLower(k) {
  2909  		case "max_connections", "max_conn":
  2910  			acc.mconns = int32(mv.(int64))
  2911  		case "max_subscriptions", "max_subs":
  2912  			acc.msubs = int32(mv.(int64))
  2913  		case "max_payload", "max_pay":
  2914  			acc.mpay = int32(mv.(int64))
  2915  		case "max_leafnodes", "max_leafs":
  2916  			acc.mleafs = int32(mv.(int64))
  2917  		default:
  2918  			if !tk.IsUsedVariable() {
  2919  				err := &configErr{tk, fmt.Sprintf("Unknown field %q parsing account limits", k)}
  2920  				*errors = append(*errors, err)
  2921  			}
  2922  		}
  2923  	}
  2924  
  2925  	return nil
  2926  }
  2927  
  2928  func parseAccountMsgTrace(mv any, topKey string, acc *Account) error {
  2929  	processDest := func(tk token, k string, v any) error {
  2930  		td, ok := v.(string)
  2931  		if !ok {
  2932  			return &configErr{tk, fmt.Sprintf("Field %q should be a string, got %T", k, v)}
  2933  		}
  2934  		if !IsValidPublishSubject(td) {
  2935  			return &configErr{tk, fmt.Sprintf("Trace destination %q is not valid", td)}
  2936  		}
  2937  		acc.traceDest = td
  2938  		return nil
  2939  	}
  2940  	processSampling := func(tk token, n int) error {
  2941  		if n <= 0 || n > 100 {
  2942  			return &configErr{tk, fmt.Sprintf("Ttrace destination sampling value %d is invalid, needs to be [1..100]", n)}
  2943  		}
  2944  		acc.traceDestSampling = n
  2945  		return nil
  2946  	}
  2947  
  2948  	var lt token
  2949  	tk, v := unwrapValue(mv, &lt)
  2950  	switch vv := v.(type) {
  2951  	case string:
  2952  		return processDest(tk, topKey, v)
  2953  	case map[string]any:
  2954  		for k, v := range vv {
  2955  			tk, v := unwrapValue(v, &lt)
  2956  			switch strings.ToLower(k) {
  2957  			case "dest":
  2958  				if err := processDest(tk, k, v); err != nil {
  2959  					return err
  2960  				}
  2961  			case "sampling":
  2962  				switch vv := v.(type) {
  2963  				case int64:
  2964  					if err := processSampling(tk, int(vv)); err != nil {
  2965  						return err
  2966  					}
  2967  				case string:
  2968  					s := strings.TrimSuffix(vv, "%")
  2969  					n, err := strconv.Atoi(s)
  2970  					if err != nil {
  2971  						return &configErr{tk, fmt.Sprintf("Invalid trace destination sampling value %q", vv)}
  2972  					}
  2973  					if err := processSampling(tk, n); err != nil {
  2974  						return err
  2975  					}
  2976  				default:
  2977  					return &configErr{tk, fmt.Sprintf("Trace destination sampling field %q should be an integer or a percentage, got %T", k, v)}
  2978  				}
  2979  			default:
  2980  				if !tk.IsUsedVariable() {
  2981  					return &configErr{tk, fmt.Sprintf("Unknown field %q parsing account message trace map/struct %q", k, topKey)}
  2982  				}
  2983  			}
  2984  		}
  2985  	default:
  2986  		return &configErr{tk, fmt.Sprintf("Expected account message trace %q to be a string or a map/struct, got %T", topKey, v)}
  2987  	}
  2988  	return nil
  2989  }
  2990  
  2991  // parseAccounts will parse the different accounts syntax.
  2992  func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]error) error {
  2993  	var (
  2994  		importStreams  []*importStream
  2995  		importServices []*importService
  2996  		exportStreams  []*export
  2997  		exportServices []*export
  2998  		lt             token
  2999  	)
  3000  	defer convertPanicToErrorList(&lt, errors)
  3001  
  3002  	tk, v := unwrapValue(v, &lt)
  3003  	switch vv := v.(type) {
  3004  	// Simple array of account names.
  3005  	case []interface{}, []string:
  3006  		m := make(map[string]struct{}, len(v.([]interface{})))
  3007  		for _, n := range v.([]interface{}) {
  3008  			tk, name := unwrapValue(n, &lt)
  3009  			ns := name.(string)
  3010  			// Check for reserved names.
  3011  			if isReservedAccount(ns) {
  3012  				err := &configErr{tk, fmt.Sprintf("%q is a Reserved Account", ns)}
  3013  				*errors = append(*errors, err)
  3014  				continue
  3015  			}
  3016  			if _, ok := m[ns]; ok {
  3017  				err := &configErr{tk, fmt.Sprintf("Duplicate Account Entry: %s", ns)}
  3018  				*errors = append(*errors, err)
  3019  				continue
  3020  			}
  3021  			opts.Accounts = append(opts.Accounts, NewAccount(ns))
  3022  			m[ns] = struct{}{}
  3023  		}
  3024  	// More common map entry
  3025  	case map[string]interface{}:
  3026  		// Track users across accounts, must be unique across
  3027  		// accounts and nkeys vs users.
  3028  		// We also want to check for users that may have been added in
  3029  		// parseAuthorization{} if that happened first.
  3030  		uorn := setupUsersAndNKeysDuplicateCheckMap(opts)
  3031  
  3032  		for aname, mv := range vv {
  3033  			tk, amv := unwrapValue(mv, &lt)
  3034  
  3035  			// Skip referenced config vars within the account block.
  3036  			if tk.IsUsedVariable() {
  3037  				continue
  3038  			}
  3039  
  3040  			// These should be maps.
  3041  			mv, ok := amv.(map[string]interface{})
  3042  			if !ok {
  3043  				err := &configErr{tk, "Expected map entries for accounts"}
  3044  				*errors = append(*errors, err)
  3045  				continue
  3046  			}
  3047  			if isReservedAccount(aname) {
  3048  				err := &configErr{tk, fmt.Sprintf("%q is a Reserved Account", aname)}
  3049  				*errors = append(*errors, err)
  3050  				continue
  3051  			}
  3052  			var (
  3053  				users   []*User
  3054  				nkeyUsr []*NkeyUser
  3055  				usersTk token
  3056  			)
  3057  			acc := NewAccount(aname)
  3058  			opts.Accounts = append(opts.Accounts, acc)
  3059  
  3060  			for k, v := range mv {
  3061  				tk, mv := unwrapValue(v, &lt)
  3062  				switch strings.ToLower(k) {
  3063  				case "nkey":
  3064  					nk, ok := mv.(string)
  3065  					if !ok || !nkeys.IsValidPublicAccountKey(nk) {
  3066  						err := &configErr{tk, fmt.Sprintf("Not a valid public nkey for an account: %q", mv)}
  3067  						*errors = append(*errors, err)
  3068  						continue
  3069  					}
  3070  					acc.Nkey = nk
  3071  				case "imports":
  3072  					streams, services, err := parseAccountImports(tk, acc, errors, warnings)
  3073  					if err != nil {
  3074  						*errors = append(*errors, err)
  3075  						continue
  3076  					}
  3077  					importStreams = append(importStreams, streams...)
  3078  					importServices = append(importServices, services...)
  3079  				case "exports":
  3080  					streams, services, err := parseAccountExports(tk, acc, errors, warnings)
  3081  					if err != nil {
  3082  						*errors = append(*errors, err)
  3083  						continue
  3084  					}
  3085  					exportStreams = append(exportStreams, streams...)
  3086  					exportServices = append(exportServices, services...)
  3087  				case "jetstream":
  3088  					err := parseJetStreamForAccount(mv, acc, errors, warnings)
  3089  					if err != nil {
  3090  						*errors = append(*errors, err)
  3091  						continue
  3092  					}
  3093  				case "users":
  3094  					var err error
  3095  					usersTk = tk
  3096  					nkeyUsr, users, err = parseUsers(mv, opts, errors, warnings)
  3097  					if err != nil {
  3098  						*errors = append(*errors, err)
  3099  						continue
  3100  					}
  3101  				case "default_permissions":
  3102  					permissions, err := parseUserPermissions(tk, errors, warnings)
  3103  					if err != nil {
  3104  						*errors = append(*errors, err)
  3105  						continue
  3106  					}
  3107  					acc.defaultPerms = permissions
  3108  				case "mappings", "maps":
  3109  					err := parseAccountMappings(tk, acc, errors, warnings)
  3110  					if err != nil {
  3111  						*errors = append(*errors, err)
  3112  						continue
  3113  					}
  3114  				case "limits":
  3115  					err := parseAccountLimits(tk, acc, errors, warnings)
  3116  					if err != nil {
  3117  						*errors = append(*errors, err)
  3118  						continue
  3119  					}
  3120  				case "msg_trace", "trace_dest":
  3121  					if err := parseAccountMsgTrace(tk, k, acc); err != nil {
  3122  						*errors = append(*errors, err)
  3123  						continue
  3124  					}
  3125  					// If trace destination is set but no sampling, set it to 100%.
  3126  					if acc.traceDest != _EMPTY_ && acc.traceDestSampling == 0 {
  3127  						acc.traceDestSampling = 100
  3128  					} else if acc.traceDestSampling > 0 && acc.traceDest == _EMPTY_ {
  3129  						// If no trace destination is provided, no trace would be
  3130  						// triggered, so if the user set a sampling value expecting
  3131  						// something to happen, want and set the value to 0 for good
  3132  						// measure.
  3133  						*warnings = append(*warnings,
  3134  							&configErr{tk, "Trace destination sampling ignored since no destination was set"})
  3135  						acc.traceDestSampling = 0
  3136  					}
  3137  				default:
  3138  					if !tk.IsUsedVariable() {
  3139  						err := &unknownConfigFieldErr{
  3140  							field: k,
  3141  							configErr: configErr{
  3142  								token: tk,
  3143  							},
  3144  						}
  3145  						*errors = append(*errors, err)
  3146  					}
  3147  				}
  3148  			}
  3149  			// Report error if there is an authorization{} block
  3150  			// with u/p or token and any user defined in accounts{}
  3151  			if len(nkeyUsr) > 0 || len(users) > 0 {
  3152  				if opts.Username != _EMPTY_ {
  3153  					err := &configErr{usersTk, "Can not have a single user/pass and accounts"}
  3154  					*errors = append(*errors, err)
  3155  					continue
  3156  				}
  3157  				if opts.Authorization != _EMPTY_ {
  3158  					err := &configErr{usersTk, "Can not have a token and accounts"}
  3159  					*errors = append(*errors, err)
  3160  					continue
  3161  				}
  3162  			}
  3163  			applyDefaultPermissions(users, nkeyUsr, acc.defaultPerms)
  3164  			for _, u := range nkeyUsr {
  3165  				if _, ok := uorn[u.Nkey]; ok {
  3166  					err := &configErr{usersTk, fmt.Sprintf("Duplicate nkey %q detected", u.Nkey)}
  3167  					*errors = append(*errors, err)
  3168  					continue
  3169  				}
  3170  				uorn[u.Nkey] = struct{}{}
  3171  				u.Account = acc
  3172  			}
  3173  			opts.Nkeys = append(opts.Nkeys, nkeyUsr...)
  3174  			for _, u := range users {
  3175  				if _, ok := uorn[u.Username]; ok {
  3176  					err := &configErr{usersTk, fmt.Sprintf("Duplicate user %q detected", u.Username)}
  3177  					*errors = append(*errors, err)
  3178  					continue
  3179  				}
  3180  				uorn[u.Username] = struct{}{}
  3181  				u.Account = acc
  3182  			}
  3183  			opts.Users = append(opts.Users, users...)
  3184  		}
  3185  	}
  3186  	lt = tk
  3187  	// Bail already if there are previous errors.
  3188  	if len(*errors) > 0 {
  3189  		return nil
  3190  	}
  3191  
  3192  	// Parse Imports and Exports here after all accounts defined.
  3193  	// Do exports first since they need to be defined for imports to succeed
  3194  	// since we do permissions checks.
  3195  
  3196  	// Create a lookup map for accounts lookups.
  3197  	am := make(map[string]*Account, len(opts.Accounts))
  3198  	for _, a := range opts.Accounts {
  3199  		am[a.Name] = a
  3200  	}
  3201  	// Do stream exports
  3202  	for _, stream := range exportStreams {
  3203  		// Make array of accounts if applicable.
  3204  		var accounts []*Account
  3205  		for _, an := range stream.accs {
  3206  			ta := am[an]
  3207  			if ta == nil {
  3208  				msg := fmt.Sprintf("%q account not defined for stream export", an)
  3209  				*errors = append(*errors, &configErr{tk, msg})
  3210  				continue
  3211  			}
  3212  			accounts = append(accounts, ta)
  3213  		}
  3214  		if err := stream.acc.addStreamExportWithAccountPos(stream.sub, accounts, stream.tPos); err != nil {
  3215  			msg := fmt.Sprintf("Error adding stream export %q: %v", stream.sub, err)
  3216  			*errors = append(*errors, &configErr{tk, msg})
  3217  			continue
  3218  		}
  3219  	}
  3220  	for _, service := range exportServices {
  3221  		// Make array of accounts if applicable.
  3222  		var accounts []*Account
  3223  		for _, an := range service.accs {
  3224  			ta := am[an]
  3225  			if ta == nil {
  3226  				msg := fmt.Sprintf("%q account not defined for service export", an)
  3227  				*errors = append(*errors, &configErr{tk, msg})
  3228  				continue
  3229  			}
  3230  			accounts = append(accounts, ta)
  3231  		}
  3232  		if err := service.acc.addServiceExportWithResponseAndAccountPos(service.sub, service.rt, accounts, service.tPos); err != nil {
  3233  			msg := fmt.Sprintf("Error adding service export %q: %v", service.sub, err)
  3234  			*errors = append(*errors, &configErr{tk, msg})
  3235  			continue
  3236  		}
  3237  
  3238  		if service.rthr != 0 {
  3239  			// Response threshold was set in options.
  3240  			if err := service.acc.SetServiceExportResponseThreshold(service.sub, service.rthr); err != nil {
  3241  				msg := fmt.Sprintf("Error adding service export response threshold for %q: %v", service.sub, err)
  3242  				*errors = append(*errors, &configErr{tk, msg})
  3243  				continue
  3244  			}
  3245  		}
  3246  
  3247  		if service.lat != nil {
  3248  			// System accounts are on be default so just make sure we have not opted out..
  3249  			if opts.NoSystemAccount {
  3250  				msg := fmt.Sprintf("Error adding service latency sampling for %q: %v", service.sub, ErrNoSysAccount.Error())
  3251  				*errors = append(*errors, &configErr{tk, msg})
  3252  				continue
  3253  			}
  3254  
  3255  			if err := service.acc.TrackServiceExportWithSampling(service.sub, service.lat.subject, int(service.lat.sampling)); err != nil {
  3256  				msg := fmt.Sprintf("Error adding service latency sampling for %q on subject %q: %v", service.sub, service.lat.subject, err)
  3257  				*errors = append(*errors, &configErr{tk, msg})
  3258  				continue
  3259  			}
  3260  		}
  3261  
  3262  		if service.atrc {
  3263  			if err := service.acc.SetServiceExportAllowTrace(service.sub, true); err != nil {
  3264  				msg := fmt.Sprintf("Error adding allow_trace for %q: %v", service.sub, err)
  3265  				*errors = append(*errors, &configErr{tk, msg})
  3266  				continue
  3267  			}
  3268  		}
  3269  	}
  3270  	for _, stream := range importStreams {
  3271  		ta := am[stream.an]
  3272  		if ta == nil {
  3273  			msg := fmt.Sprintf("%q account not defined for stream import", stream.an)
  3274  			*errors = append(*errors, &configErr{tk, msg})
  3275  			continue
  3276  		}
  3277  		if stream.pre != _EMPTY_ {
  3278  			if err := stream.acc.addStreamImportWithClaim(ta, stream.sub, stream.pre, stream.atrc, nil); err != nil {
  3279  				msg := fmt.Sprintf("Error adding stream import %q: %v", stream.sub, err)
  3280  				*errors = append(*errors, &configErr{tk, msg})
  3281  				continue
  3282  			}
  3283  		} else {
  3284  			if err := stream.acc.addMappedStreamImportWithClaim(ta, stream.sub, stream.to, stream.atrc, nil); err != nil {
  3285  				msg := fmt.Sprintf("Error adding stream import %q: %v", stream.sub, err)
  3286  				*errors = append(*errors, &configErr{tk, msg})
  3287  				continue
  3288  			}
  3289  		}
  3290  	}
  3291  	for _, service := range importServices {
  3292  		ta := am[service.an]
  3293  		if ta == nil {
  3294  			msg := fmt.Sprintf("%q account not defined for service import", service.an)
  3295  			*errors = append(*errors, &configErr{tk, msg})
  3296  			continue
  3297  		}
  3298  		if service.to == _EMPTY_ {
  3299  			service.to = service.sub
  3300  		}
  3301  		if err := service.acc.AddServiceImport(ta, service.to, service.sub); err != nil {
  3302  			msg := fmt.Sprintf("Error adding service import %q: %v", service.sub, err)
  3303  			*errors = append(*errors, &configErr{tk, msg})
  3304  			continue
  3305  		}
  3306  		if err := service.acc.SetServiceImportSharing(ta, service.sub, service.share); err != nil {
  3307  			msg := fmt.Sprintf("Error setting service import sharing %q: %v", service.sub, err)
  3308  			*errors = append(*errors, &configErr{tk, msg})
  3309  			continue
  3310  		}
  3311  	}
  3312  
  3313  	return nil
  3314  }
  3315  
  3316  // Parse the account exports
  3317  func parseAccountExports(v interface{}, acc *Account, errors, warnings *[]error) ([]*export, []*export, error) {
  3318  	var lt token
  3319  	defer convertPanicToErrorList(&lt, errors)
  3320  
  3321  	// This should be an array of objects/maps.
  3322  	tk, v := unwrapValue(v, &lt)
  3323  	ims, ok := v.([]interface{})
  3324  	if !ok {
  3325  		return nil, nil, &configErr{tk, fmt.Sprintf("Exports should be an array, got %T", v)}
  3326  	}
  3327  
  3328  	var services []*export
  3329  	var streams []*export
  3330  
  3331  	for _, v := range ims {
  3332  		// Should have stream or service
  3333  		stream, service, err := parseExportStreamOrService(v, errors, warnings)
  3334  		if err != nil {
  3335  			*errors = append(*errors, err)
  3336  			continue
  3337  		}
  3338  		if service != nil {
  3339  			service.acc = acc
  3340  			services = append(services, service)
  3341  		}
  3342  		if stream != nil {
  3343  			stream.acc = acc
  3344  			streams = append(streams, stream)
  3345  		}
  3346  	}
  3347  	return streams, services, nil
  3348  }
  3349  
  3350  // Parse the account imports
  3351  func parseAccountImports(v interface{}, acc *Account, errors, warnings *[]error) ([]*importStream, []*importService, error) {
  3352  	var lt token
  3353  	defer convertPanicToErrorList(&lt, errors)
  3354  
  3355  	// This should be an array of objects/maps.
  3356  	tk, v := unwrapValue(v, &lt)
  3357  	ims, ok := v.([]interface{})
  3358  	if !ok {
  3359  		return nil, nil, &configErr{tk, fmt.Sprintf("Imports should be an array, got %T", v)}
  3360  	}
  3361  
  3362  	var services []*importService
  3363  	var streams []*importStream
  3364  	svcSubjects := map[string]*importService{}
  3365  
  3366  	for _, v := range ims {
  3367  		// Should have stream or service
  3368  		stream, service, err := parseImportStreamOrService(v, errors, warnings)
  3369  		if err != nil {
  3370  			*errors = append(*errors, err)
  3371  			continue
  3372  		}
  3373  		if service != nil {
  3374  			if dup := svcSubjects[service.to]; dup != nil {
  3375  				tk, _ := unwrapValue(v, &lt)
  3376  				err := &configErr{tk,
  3377  					fmt.Sprintf("Duplicate service import subject %q, previously used in import for account %q, subject %q",
  3378  						service.to, dup.an, dup.sub)}
  3379  				*errors = append(*errors, err)
  3380  				continue
  3381  			}
  3382  			svcSubjects[service.to] = service
  3383  			service.acc = acc
  3384  			services = append(services, service)
  3385  		}
  3386  		if stream != nil {
  3387  			stream.acc = acc
  3388  			streams = append(streams, stream)
  3389  		}
  3390  	}
  3391  	return streams, services, nil
  3392  }
  3393  
  3394  // Helper to parse an embedded account description for imported services or streams.
  3395  func parseAccount(v map[string]interface{}, errors, warnings *[]error) (string, string, error) {
  3396  	var lt token
  3397  	defer convertPanicToErrorList(&lt, errors)
  3398  
  3399  	var accountName, subject string
  3400  	for mk, mv := range v {
  3401  		tk, mv := unwrapValue(mv, &lt)
  3402  		switch strings.ToLower(mk) {
  3403  		case "account":
  3404  			accountName = mv.(string)
  3405  		case "subject":
  3406  			subject = mv.(string)
  3407  		default:
  3408  			if !tk.IsUsedVariable() {
  3409  				err := &unknownConfigFieldErr{
  3410  					field: mk,
  3411  					configErr: configErr{
  3412  						token: tk,
  3413  					},
  3414  				}
  3415  				*errors = append(*errors, err)
  3416  			}
  3417  		}
  3418  	}
  3419  	return accountName, subject, nil
  3420  }
  3421  
  3422  // Parse an export stream or service.
  3423  // e.g.
  3424  // {stream: "public.>"} # No accounts means public.
  3425  // {stream: "synadia.private.>", accounts: [cncf, natsio]}
  3426  // {service: "pub.request"} # No accounts means public.
  3427  // {service: "pub.special.request", accounts: [nats.io]}
  3428  func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*export, *export, error) {
  3429  	var (
  3430  		curStream  *export
  3431  		curService *export
  3432  		accounts   []string
  3433  		rt         ServiceRespType
  3434  		rtSeen     bool
  3435  		rtToken    token
  3436  		lat        *serviceLatency
  3437  		threshSeen bool
  3438  		thresh     time.Duration
  3439  		latToken   token
  3440  		lt         token
  3441  		accTokPos  uint
  3442  		atrc       bool
  3443  		atrcSeen   bool
  3444  		atrcToken  token
  3445  	)
  3446  	defer convertPanicToErrorList(&lt, errors)
  3447  
  3448  	tk, v := unwrapValue(v, &lt)
  3449  	vv, ok := v.(map[string]interface{})
  3450  	if !ok {
  3451  		return nil, nil, &configErr{tk, fmt.Sprintf("Export Items should be a map with type entry, got %T", v)}
  3452  	}
  3453  	for mk, mv := range vv {
  3454  		tk, mv := unwrapValue(mv, &lt)
  3455  		switch strings.ToLower(mk) {
  3456  		case "stream":
  3457  			if curService != nil {
  3458  				err := &configErr{tk, fmt.Sprintf("Detected stream %q but already saw a service", mv)}
  3459  				*errors = append(*errors, err)
  3460  				continue
  3461  			}
  3462  			if rtToken != nil {
  3463  				err := &configErr{rtToken, "Detected response directive on non-service"}
  3464  				*errors = append(*errors, err)
  3465  				continue
  3466  			}
  3467  			if latToken != nil {
  3468  				err := &configErr{latToken, "Detected latency directive on non-service"}
  3469  				*errors = append(*errors, err)
  3470  				continue
  3471  			}
  3472  			if atrcToken != nil {
  3473  				err := &configErr{atrcToken, "Detected allow_trace directive on non-service"}
  3474  				*errors = append(*errors, err)
  3475  				continue
  3476  			}
  3477  			mvs, ok := mv.(string)
  3478  			if !ok {
  3479  				err := &configErr{tk, fmt.Sprintf("Expected stream name to be string, got %T", mv)}
  3480  				*errors = append(*errors, err)
  3481  				continue
  3482  			}
  3483  			curStream = &export{sub: mvs}
  3484  			if accounts != nil {
  3485  				curStream.accs = accounts
  3486  			}
  3487  		case "service":
  3488  			if curStream != nil {
  3489  				err := &configErr{tk, fmt.Sprintf("Detected service %q but already saw a stream", mv)}
  3490  				*errors = append(*errors, err)
  3491  				continue
  3492  			}
  3493  			mvs, ok := mv.(string)
  3494  			if !ok {
  3495  				err := &configErr{tk, fmt.Sprintf("Expected service name to be string, got %T", mv)}
  3496  				*errors = append(*errors, err)
  3497  				continue
  3498  			}
  3499  			curService = &export{sub: mvs}
  3500  			if accounts != nil {
  3501  				curService.accs = accounts
  3502  			}
  3503  			if rtSeen {
  3504  				curService.rt = rt
  3505  			}
  3506  			if lat != nil {
  3507  				curService.lat = lat
  3508  			}
  3509  			if threshSeen {
  3510  				curService.rthr = thresh
  3511  			}
  3512  			if atrcSeen {
  3513  				curService.atrc = atrc
  3514  			}
  3515  		case "response", "response_type":
  3516  			if rtSeen {
  3517  				err := &configErr{tk, "Duplicate response type definition"}
  3518  				*errors = append(*errors, err)
  3519  				continue
  3520  			}
  3521  			rtSeen = true
  3522  			rtToken = tk
  3523  			mvs, ok := mv.(string)
  3524  			if !ok {
  3525  				err := &configErr{tk, fmt.Sprintf("Expected response type to be string, got %T", mv)}
  3526  				*errors = append(*errors, err)
  3527  				continue
  3528  			}
  3529  			switch strings.ToLower(mvs) {
  3530  			case "single", "singleton":
  3531  				rt = Singleton
  3532  			case "stream":
  3533  				rt = Streamed
  3534  			case "chunk", "chunked":
  3535  				rt = Chunked
  3536  			default:
  3537  				err := &configErr{tk, fmt.Sprintf("Unknown response type: %q", mvs)}
  3538  				*errors = append(*errors, err)
  3539  				continue
  3540  			}
  3541  			if curService != nil {
  3542  				curService.rt = rt
  3543  			}
  3544  			if curStream != nil {
  3545  				err := &configErr{tk, "Detected response directive on non-service"}
  3546  				*errors = append(*errors, err)
  3547  			}
  3548  		case "threshold", "response_threshold", "response_max_time", "response_time":
  3549  			if threshSeen {
  3550  				err := &configErr{tk, "Duplicate response threshold detected"}
  3551  				*errors = append(*errors, err)
  3552  				continue
  3553  			}
  3554  			threshSeen = true
  3555  			mvs, ok := mv.(string)
  3556  			if !ok {
  3557  				err := &configErr{tk, fmt.Sprintf("Expected response threshold to be a parseable time duration, got %T", mv)}
  3558  				*errors = append(*errors, err)
  3559  				continue
  3560  			}
  3561  			var err error
  3562  			thresh, err = time.ParseDuration(mvs)
  3563  			if err != nil {
  3564  				err := &configErr{tk, fmt.Sprintf("Expected response threshold to be a parseable time duration, got %q", mvs)}
  3565  				*errors = append(*errors, err)
  3566  				continue
  3567  			}
  3568  			if curService != nil {
  3569  				curService.rthr = thresh
  3570  			}
  3571  			if curStream != nil {
  3572  				err := &configErr{tk, "Detected response directive on non-service"}
  3573  				*errors = append(*errors, err)
  3574  			}
  3575  		case "accounts":
  3576  			for _, iv := range mv.([]interface{}) {
  3577  				_, mv := unwrapValue(iv, &lt)
  3578  				accounts = append(accounts, mv.(string))
  3579  			}
  3580  			if curStream != nil {
  3581  				curStream.accs = accounts
  3582  			} else if curService != nil {
  3583  				curService.accs = accounts
  3584  			}
  3585  		case "latency":
  3586  			latToken = tk
  3587  			var err error
  3588  			lat, err = parseServiceLatency(tk, mv)
  3589  			if err != nil {
  3590  				*errors = append(*errors, err)
  3591  				continue
  3592  			}
  3593  			if curStream != nil {
  3594  				err = &configErr{tk, "Detected latency directive on non-service"}
  3595  				*errors = append(*errors, err)
  3596  				continue
  3597  			}
  3598  			if curService != nil {
  3599  				curService.lat = lat
  3600  			}
  3601  		case "account_token_position":
  3602  			accTokPos = uint(mv.(int64))
  3603  		case "allow_trace":
  3604  			atrcSeen = true
  3605  			atrcToken = tk
  3606  			atrc = mv.(bool)
  3607  			if curStream != nil {
  3608  				*errors = append(*errors,
  3609  					&configErr{tk, "Detected allow_trace directive on non-service"})
  3610  				continue
  3611  			}
  3612  			if curService != nil {
  3613  				curService.atrc = atrc
  3614  			}
  3615  		default:
  3616  			if !tk.IsUsedVariable() {
  3617  				err := &unknownConfigFieldErr{
  3618  					field: mk,
  3619  					configErr: configErr{
  3620  						token: tk,
  3621  					},
  3622  				}
  3623  				*errors = append(*errors, err)
  3624  			}
  3625  		}
  3626  	}
  3627  	if curStream != nil {
  3628  		curStream.tPos = accTokPos
  3629  	}
  3630  	if curService != nil {
  3631  		curService.tPos = accTokPos
  3632  	}
  3633  	return curStream, curService, nil
  3634  }
  3635  
  3636  // parseServiceLatency returns a latency config block.
  3637  func parseServiceLatency(root token, v interface{}) (l *serviceLatency, retErr error) {
  3638  	var lt token
  3639  	defer convertPanicToError(&lt, &retErr)
  3640  
  3641  	if subject, ok := v.(string); ok {
  3642  		return &serviceLatency{
  3643  			subject:  subject,
  3644  			sampling: DEFAULT_SERVICE_LATENCY_SAMPLING,
  3645  		}, nil
  3646  	}
  3647  
  3648  	latency, ok := v.(map[string]interface{})
  3649  	if !ok {
  3650  		return nil, &configErr{token: root,
  3651  			reason: fmt.Sprintf("Expected latency entry to be a map/struct or string, got %T", v)}
  3652  	}
  3653  
  3654  	sl := serviceLatency{
  3655  		sampling: DEFAULT_SERVICE_LATENCY_SAMPLING,
  3656  	}
  3657  
  3658  	// Read sampling value.
  3659  	if v, ok := latency["sampling"]; ok {
  3660  		tk, v := unwrapValue(v, &lt)
  3661  		header := false
  3662  		var sample int64
  3663  		switch vv := v.(type) {
  3664  		case int64:
  3665  			// Sample is an int, like 50.
  3666  			sample = vv
  3667  		case string:
  3668  			// Sample is a string, like "50%".
  3669  			if strings.ToLower(strings.TrimSpace(vv)) == "headers" {
  3670  				header = true
  3671  				sample = 0
  3672  				break
  3673  			}
  3674  			s := strings.TrimSuffix(vv, "%")
  3675  			n, err := strconv.Atoi(s)
  3676  			if err != nil {
  3677  				return nil, &configErr{token: tk,
  3678  					reason: fmt.Sprintf("Failed to parse latency sample: %v", err)}
  3679  			}
  3680  			sample = int64(n)
  3681  		default:
  3682  			return nil, &configErr{token: tk,
  3683  				reason: fmt.Sprintf("Expected latency sample to be a string or map/struct, got %T", v)}
  3684  		}
  3685  		if !header {
  3686  			if sample < 1 || sample > 100 {
  3687  				return nil, &configErr{token: tk,
  3688  					reason: ErrBadSampling.Error()}
  3689  			}
  3690  		}
  3691  
  3692  		sl.sampling = int8(sample)
  3693  	}
  3694  
  3695  	// Read subject value.
  3696  	v, ok = latency["subject"]
  3697  	if !ok {
  3698  		return nil, &configErr{token: root,
  3699  			reason: "Latency subject required, but missing"}
  3700  	}
  3701  
  3702  	tk, v := unwrapValue(v, &lt)
  3703  	subject, ok := v.(string)
  3704  	if !ok {
  3705  		return nil, &configErr{token: tk,
  3706  			reason: fmt.Sprintf("Expected latency subject to be a string, got %T", subject)}
  3707  	}
  3708  	sl.subject = subject
  3709  
  3710  	return &sl, nil
  3711  }
  3712  
  3713  // Parse an import stream or service.
  3714  // e.g.
  3715  // {stream: {account: "synadia", subject:"public.synadia"}, prefix: "imports.synadia"}
  3716  // {stream: {account: "synadia", subject:"synadia.private.*"}}
  3717  // {service: {account: "synadia", subject: "pub.special.request"}, to: "synadia.request"}
  3718  func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*importStream, *importService, error) {
  3719  	var (
  3720  		curStream  *importStream
  3721  		curService *importService
  3722  		pre, to    string
  3723  		share      bool
  3724  		lt         token
  3725  		atrc       bool
  3726  		atrcSeen   bool
  3727  		atrcToken  token
  3728  	)
  3729  	defer convertPanicToErrorList(&lt, errors)
  3730  
  3731  	tk, mv := unwrapValue(v, &lt)
  3732  	vv, ok := mv.(map[string]interface{})
  3733  	if !ok {
  3734  		return nil, nil, &configErr{tk, fmt.Sprintf("Import Items should be a map with type entry, got %T", mv)}
  3735  	}
  3736  	for mk, mv := range vv {
  3737  		tk, mv := unwrapValue(mv, &lt)
  3738  		switch strings.ToLower(mk) {
  3739  		case "stream":
  3740  			if curService != nil {
  3741  				err := &configErr{tk, "Detected stream but already saw a service"}
  3742  				*errors = append(*errors, err)
  3743  				continue
  3744  			}
  3745  			ac, ok := mv.(map[string]interface{})
  3746  			if !ok {
  3747  				err := &configErr{tk, fmt.Sprintf("Stream entry should be an account map, got %T", mv)}
  3748  				*errors = append(*errors, err)
  3749  				continue
  3750  			}
  3751  			// Make sure this is a map with account and subject
  3752  			accountName, subject, err := parseAccount(ac, errors, warnings)
  3753  			if err != nil {
  3754  				*errors = append(*errors, err)
  3755  				continue
  3756  			}
  3757  			if accountName == _EMPTY_ || subject == _EMPTY_ {
  3758  				err := &configErr{tk, "Expect an account name and a subject"}
  3759  				*errors = append(*errors, err)
  3760  				continue
  3761  			}
  3762  			curStream = &importStream{an: accountName, sub: subject}
  3763  			if to != _EMPTY_ {
  3764  				curStream.to = to
  3765  			}
  3766  			if pre != _EMPTY_ {
  3767  				curStream.pre = pre
  3768  			}
  3769  			if atrcSeen {
  3770  				curStream.atrc = atrc
  3771  			}
  3772  		case "service":
  3773  			if curStream != nil {
  3774  				err := &configErr{tk, "Detected service but already saw a stream"}
  3775  				*errors = append(*errors, err)
  3776  				continue
  3777  			}
  3778  			if atrcToken != nil {
  3779  				err := &configErr{atrcToken, "Detected allow_trace directive on a non-stream"}
  3780  				*errors = append(*errors, err)
  3781  				continue
  3782  			}
  3783  			ac, ok := mv.(map[string]interface{})
  3784  			if !ok {
  3785  				err := &configErr{tk, fmt.Sprintf("Service entry should be an account map, got %T", mv)}
  3786  				*errors = append(*errors, err)
  3787  				continue
  3788  			}
  3789  			// Make sure this is a map with account and subject
  3790  			accountName, subject, err := parseAccount(ac, errors, warnings)
  3791  			if err != nil {
  3792  				*errors = append(*errors, err)
  3793  				continue
  3794  			}
  3795  			if accountName == _EMPTY_ || subject == _EMPTY_ {
  3796  				err := &configErr{tk, "Expect an account name and a subject"}
  3797  				*errors = append(*errors, err)
  3798  				continue
  3799  			}
  3800  			curService = &importService{an: accountName, sub: subject}
  3801  			if to != _EMPTY_ {
  3802  				curService.to = to
  3803  			} else {
  3804  				curService.to = subject
  3805  			}
  3806  			curService.share = share
  3807  		case "prefix":
  3808  			pre = mv.(string)
  3809  			if curStream != nil {
  3810  				curStream.pre = pre
  3811  			}
  3812  		case "to":
  3813  			to = mv.(string)
  3814  			if curService != nil {
  3815  				curService.to = to
  3816  			}
  3817  			if curStream != nil {
  3818  				curStream.to = to
  3819  				if curStream.pre != _EMPTY_ {
  3820  					err := &configErr{tk, "Stream import can not have a 'prefix' and a 'to' property"}
  3821  					*errors = append(*errors, err)
  3822  					continue
  3823  				}
  3824  			}
  3825  		case "share":
  3826  			share = mv.(bool)
  3827  			if curService != nil {
  3828  				curService.share = share
  3829  			}
  3830  		case "allow_trace":
  3831  			if curService != nil {
  3832  				err := &configErr{tk, "Detected allow_trace directive on a non-stream"}
  3833  				*errors = append(*errors, err)
  3834  				continue
  3835  			}
  3836  			atrcSeen = true
  3837  			atrc = mv.(bool)
  3838  			atrcToken = tk
  3839  			if curStream != nil {
  3840  				curStream.atrc = atrc
  3841  			}
  3842  		default:
  3843  			if !tk.IsUsedVariable() {
  3844  				err := &unknownConfigFieldErr{
  3845  					field: mk,
  3846  					configErr: configErr{
  3847  						token: tk,
  3848  					},
  3849  				}
  3850  				*errors = append(*errors, err)
  3851  			}
  3852  		}
  3853  
  3854  	}
  3855  	return curStream, curService, nil
  3856  }
  3857  
  3858  // Apply permission defaults to users/nkeyuser that don't have their own.
  3859  func applyDefaultPermissions(users []*User, nkeys []*NkeyUser, defaultP *Permissions) {
  3860  	if defaultP == nil {
  3861  		return
  3862  	}
  3863  	for _, user := range users {
  3864  		if user.Permissions == nil {
  3865  			user.Permissions = defaultP
  3866  		}
  3867  	}
  3868  	for _, user := range nkeys {
  3869  		if user.Permissions == nil {
  3870  			user.Permissions = defaultP
  3871  		}
  3872  	}
  3873  }
  3874  
  3875  // Helper function to parse Authorization configs.
  3876  func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings *[]error) (*authorization, error) {
  3877  	var (
  3878  		am   map[string]interface{}
  3879  		tk   token
  3880  		lt   token
  3881  		auth = &authorization{}
  3882  	)
  3883  	defer convertPanicToErrorList(&lt, errors)
  3884  
  3885  	_, v = unwrapValue(v, &lt)
  3886  	am = v.(map[string]interface{})
  3887  	for mk, mv := range am {
  3888  		tk, mv = unwrapValue(mv, &lt)
  3889  		switch strings.ToLower(mk) {
  3890  		case "user", "username":
  3891  			auth.user = mv.(string)
  3892  		case "pass", "password":
  3893  			auth.pass = mv.(string)
  3894  		case "token":
  3895  			auth.token = mv.(string)
  3896  		case "timeout":
  3897  			at := float64(1)
  3898  			switch mv := mv.(type) {
  3899  			case int64:
  3900  				at = float64(mv)
  3901  			case float64:
  3902  				at = mv
  3903  			}
  3904  			auth.timeout = at
  3905  		case "users":
  3906  			nkeys, users, err := parseUsers(tk, opts, errors, warnings)
  3907  			if err != nil {
  3908  				*errors = append(*errors, err)
  3909  				continue
  3910  			}
  3911  			auth.users = users
  3912  			auth.nkeys = nkeys
  3913  		case "default_permission", "default_permissions", "permissions":
  3914  			permissions, err := parseUserPermissions(tk, errors, warnings)
  3915  			if err != nil {
  3916  				*errors = append(*errors, err)
  3917  				continue
  3918  			}
  3919  			auth.defaultPermissions = permissions
  3920  		case "auth_callout", "auth_hook":
  3921  			ac, err := parseAuthCallout(tk, errors, warnings)
  3922  			if err != nil {
  3923  				*errors = append(*errors, err)
  3924  				continue
  3925  			}
  3926  			auth.callout = ac
  3927  		default:
  3928  			if !tk.IsUsedVariable() {
  3929  				err := &unknownConfigFieldErr{
  3930  					field: mk,
  3931  					configErr: configErr{
  3932  						token: tk,
  3933  					},
  3934  				}
  3935  				*errors = append(*errors, err)
  3936  			}
  3937  			continue
  3938  		}
  3939  
  3940  		applyDefaultPermissions(auth.users, auth.nkeys, auth.defaultPermissions)
  3941  	}
  3942  	return auth, nil
  3943  }
  3944  
  3945  // Helper function to parse multiple users array with optional permissions.
  3946  func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]error) ([]*NkeyUser, []*User, error) {
  3947  	var (
  3948  		tk    token
  3949  		lt    token
  3950  		keys  []*NkeyUser
  3951  		users = []*User{}
  3952  	)
  3953  	defer convertPanicToErrorList(&lt, errors)
  3954  	tk, mv = unwrapValue(mv, &lt)
  3955  
  3956  	// Make sure we have an array
  3957  	uv, ok := mv.([]interface{})
  3958  	if !ok {
  3959  		return nil, nil, &configErr{tk, fmt.Sprintf("Expected users field to be an array, got %v", mv)}
  3960  	}
  3961  	for _, u := range uv {
  3962  		tk, u = unwrapValue(u, &lt)
  3963  
  3964  		// Check its a map/struct
  3965  		um, ok := u.(map[string]interface{})
  3966  		if !ok {
  3967  			err := &configErr{tk, fmt.Sprintf("Expected user entry to be a map/struct, got %v", u)}
  3968  			*errors = append(*errors, err)
  3969  			continue
  3970  		}
  3971  
  3972  		var (
  3973  			user  = &User{}
  3974  			nkey  = &NkeyUser{}
  3975  			perms *Permissions
  3976  			err   error
  3977  		)
  3978  		for k, v := range um {
  3979  			// Also needs to unwrap first
  3980  			tk, v = unwrapValue(v, &lt)
  3981  
  3982  			switch strings.ToLower(k) {
  3983  			case "nkey":
  3984  				nkey.Nkey = v.(string)
  3985  			case "user", "username":
  3986  				user.Username = v.(string)
  3987  			case "pass", "password":
  3988  				user.Password = v.(string)
  3989  			case "permission", "permissions", "authorization":
  3990  				perms, err = parseUserPermissions(tk, errors, warnings)
  3991  				if err != nil {
  3992  					*errors = append(*errors, err)
  3993  					continue
  3994  				}
  3995  			case "allowed_connection_types", "connection_types", "clients":
  3996  				cts := parseAllowedConnectionTypes(tk, &lt, v, errors, warnings)
  3997  				nkey.AllowedConnectionTypes = cts
  3998  				user.AllowedConnectionTypes = cts
  3999  			default:
  4000  				if !tk.IsUsedVariable() {
  4001  					err := &unknownConfigFieldErr{
  4002  						field: k,
  4003  						configErr: configErr{
  4004  							token: tk,
  4005  						},
  4006  					}
  4007  					*errors = append(*errors, err)
  4008  					continue
  4009  				}
  4010  			}
  4011  		}
  4012  		// Place perms if we have them.
  4013  		if perms != nil {
  4014  			// nkey takes precedent.
  4015  			if nkey.Nkey != _EMPTY_ {
  4016  				nkey.Permissions = perms
  4017  			} else {
  4018  				user.Permissions = perms
  4019  			}
  4020  		}
  4021  
  4022  		// Check to make sure we have at least an nkey or username <password> defined.
  4023  		if nkey.Nkey == _EMPTY_ && user.Username == _EMPTY_ {
  4024  			return nil, nil, &configErr{tk, "User entry requires a user"}
  4025  		} else if nkey.Nkey != _EMPTY_ {
  4026  			// Make sure the nkey a proper public nkey for a user..
  4027  			if !nkeys.IsValidPublicUserKey(nkey.Nkey) {
  4028  				return nil, nil, &configErr{tk, "Not a valid public nkey for a user"}
  4029  			}
  4030  			// If we have user or password defined here that is an error.
  4031  			if user.Username != _EMPTY_ || user.Password != _EMPTY_ {
  4032  				return nil, nil, &configErr{tk, "Nkey users do not take usernames or passwords"}
  4033  			}
  4034  			keys = append(keys, nkey)
  4035  		} else {
  4036  			users = append(users, user)
  4037  		}
  4038  	}
  4039  	return keys, users, nil
  4040  }
  4041  
  4042  func parseAllowedConnectionTypes(tk token, lt *token, mv interface{}, errors *[]error, warnings *[]error) map[string]struct{} {
  4043  	cts, err := parseStringArray("allowed connection types", tk, lt, mv, errors, warnings)
  4044  	// If error, it has already been added to the `errors` array, simply return
  4045  	if err != nil {
  4046  		return nil
  4047  	}
  4048  	m, err := convertAllowedConnectionTypes(cts)
  4049  	if err != nil {
  4050  		*errors = append(*errors, &configErr{tk, err.Error()})
  4051  	}
  4052  	return m
  4053  }
  4054  
  4055  // Helper function to parse auth callouts.
  4056  func parseAuthCallout(mv interface{}, errors, warnings *[]error) (*AuthCallout, error) {
  4057  	var (
  4058  		tk token
  4059  		lt token
  4060  		ac = &AuthCallout{}
  4061  	)
  4062  	defer convertPanicToErrorList(&lt, errors)
  4063  
  4064  	tk, mv = unwrapValue(mv, &lt)
  4065  	pm, ok := mv.(map[string]interface{})
  4066  	if !ok {
  4067  		return nil, &configErr{tk, fmt.Sprintf("Expected authorization callout to be a map/struct, got %+v", mv)}
  4068  	}
  4069  	for k, v := range pm {
  4070  		tk, mv = unwrapValue(v, &lt)
  4071  
  4072  		switch strings.ToLower(k) {
  4073  		case "issuer":
  4074  			ac.Issuer = mv.(string)
  4075  			if !nkeys.IsValidPublicAccountKey(ac.Issuer) {
  4076  				return nil, &configErr{tk, fmt.Sprintf("Expected callout user to be a valid public account nkey, got %q", ac.Issuer)}
  4077  			}
  4078  		case "account", "acc":
  4079  			ac.Account = mv.(string)
  4080  		case "auth_users", "users":
  4081  			aua, ok := mv.([]interface{})
  4082  			if !ok {
  4083  				return nil, &configErr{tk, fmt.Sprintf("Expected auth_users field to be an array, got %T", v)}
  4084  			}
  4085  			for _, uv := range aua {
  4086  				_, uv = unwrapValue(uv, &lt)
  4087  				ac.AuthUsers = append(ac.AuthUsers, uv.(string))
  4088  			}
  4089  		case "xkey", "key":
  4090  			ac.XKey = mv.(string)
  4091  			if !nkeys.IsValidPublicCurveKey(ac.XKey) {
  4092  				return nil, &configErr{tk, fmt.Sprintf("Expected callout xkey to be a valid public xkey, got %q", ac.XKey)}
  4093  			}
  4094  		default:
  4095  			if !tk.IsUsedVariable() {
  4096  				err := &configErr{tk, fmt.Sprintf("Unknown field %q parsing authorization callout", k)}
  4097  				*errors = append(*errors, err)
  4098  			}
  4099  		}
  4100  	}
  4101  	// Make sure we have all defined. All fields are required.
  4102  	// If no account specified, selet $G.
  4103  	if ac.Account == _EMPTY_ {
  4104  		ac.Account = globalAccountName
  4105  	}
  4106  	if ac.Issuer == _EMPTY_ {
  4107  		return nil, &configErr{tk, "Authorization callouts require an issuer to be specified"}
  4108  	}
  4109  	if len(ac.AuthUsers) == 0 {
  4110  		return nil, &configErr{tk, "Authorization callouts require authorized users to be specified"}
  4111  	}
  4112  	return ac, nil
  4113  }
  4114  
  4115  // Helper function to parse user/account permissions
  4116  func parseUserPermissions(mv interface{}, errors, warnings *[]error) (*Permissions, error) {
  4117  	var (
  4118  		tk token
  4119  		lt token
  4120  		p  = &Permissions{}
  4121  	)
  4122  	defer convertPanicToErrorList(&lt, errors)
  4123  
  4124  	tk, mv = unwrapValue(mv, &lt)
  4125  	pm, ok := mv.(map[string]interface{})
  4126  	if !ok {
  4127  		return nil, &configErr{tk, fmt.Sprintf("Expected permissions to be a map/struct, got %+v", mv)}
  4128  	}
  4129  	for k, v := range pm {
  4130  		tk, mv = unwrapValue(v, &lt)
  4131  
  4132  		switch strings.ToLower(k) {
  4133  		// For routes:
  4134  		// Import is Publish
  4135  		// Export is Subscribe
  4136  		case "pub", "publish", "import":
  4137  			perms, err := parseVariablePermissions(mv, errors, warnings)
  4138  			if err != nil {
  4139  				*errors = append(*errors, err)
  4140  				continue
  4141  			}
  4142  			p.Publish = perms
  4143  		case "sub", "subscribe", "export":
  4144  			perms, err := parseVariablePermissions(mv, errors, warnings)
  4145  			if err != nil {
  4146  				*errors = append(*errors, err)
  4147  				continue
  4148  			}
  4149  			p.Subscribe = perms
  4150  		case "publish_allow_responses", "allow_responses":
  4151  			rp := &ResponsePermission{
  4152  				MaxMsgs: DEFAULT_ALLOW_RESPONSE_MAX_MSGS,
  4153  				Expires: DEFAULT_ALLOW_RESPONSE_EXPIRATION,
  4154  			}
  4155  			// Try boolean first
  4156  			responses, ok := mv.(bool)
  4157  			if ok {
  4158  				if responses {
  4159  					p.Response = rp
  4160  				}
  4161  			} else {
  4162  				p.Response = parseAllowResponses(v, errors, warnings)
  4163  			}
  4164  			if p.Response != nil {
  4165  				if p.Publish == nil {
  4166  					p.Publish = &SubjectPermission{}
  4167  				}
  4168  				if p.Publish.Allow == nil {
  4169  					// We turn off the blanket allow statement.
  4170  					p.Publish.Allow = []string{}
  4171  				}
  4172  			}
  4173  		default:
  4174  			if !tk.IsUsedVariable() {
  4175  				err := &configErr{tk, fmt.Sprintf("Unknown field %q parsing permissions", k)}
  4176  				*errors = append(*errors, err)
  4177  			}
  4178  		}
  4179  	}
  4180  	return p, nil
  4181  }
  4182  
  4183  // Top level parser for authorization configurations.
  4184  func parseVariablePermissions(v interface{}, errors, warnings *[]error) (*SubjectPermission, error) {
  4185  	switch vv := v.(type) {
  4186  	case map[string]interface{}:
  4187  		// New style with allow and/or deny properties.
  4188  		return parseSubjectPermission(vv, errors, warnings)
  4189  	default:
  4190  		// Old style
  4191  		return parseOldPermissionStyle(v, errors, warnings)
  4192  	}
  4193  }
  4194  
  4195  // Helper function to parse subject singletons and/or arrays
  4196  func parsePermSubjects(v interface{}, errors, warnings *[]error) ([]string, error) {
  4197  	var lt token
  4198  	defer convertPanicToErrorList(&lt, errors)
  4199  
  4200  	tk, v := unwrapValue(v, &lt)
  4201  
  4202  	var subjects []string
  4203  	switch vv := v.(type) {
  4204  	case string:
  4205  		subjects = append(subjects, vv)
  4206  	case []string:
  4207  		subjects = vv
  4208  	case []interface{}:
  4209  		for _, i := range vv {
  4210  			tk, i := unwrapValue(i, &lt)
  4211  
  4212  			subject, ok := i.(string)
  4213  			if !ok {
  4214  				return nil, &configErr{tk, "Subject in permissions array cannot be cast to string"}
  4215  			}
  4216  			subjects = append(subjects, subject)
  4217  		}
  4218  	default:
  4219  		return nil, &configErr{tk, fmt.Sprintf("Expected subject permissions to be a subject, or array of subjects, got %T", v)}
  4220  	}
  4221  	if err := checkPermSubjectArray(subjects); err != nil {
  4222  		return nil, &configErr{tk, err.Error()}
  4223  	}
  4224  	return subjects, nil
  4225  }
  4226  
  4227  // Helper function to parse a ResponsePermission.
  4228  func parseAllowResponses(v interface{}, errors, warnings *[]error) *ResponsePermission {
  4229  	var lt token
  4230  	defer convertPanicToErrorList(&lt, errors)
  4231  
  4232  	tk, v := unwrapValue(v, &lt)
  4233  	// Check if this is a map.
  4234  	pm, ok := v.(map[string]interface{})
  4235  	if !ok {
  4236  		err := &configErr{tk, "error parsing response permissions, expected a boolean or a map"}
  4237  		*errors = append(*errors, err)
  4238  		return nil
  4239  	}
  4240  
  4241  	rp := &ResponsePermission{
  4242  		MaxMsgs: DEFAULT_ALLOW_RESPONSE_MAX_MSGS,
  4243  		Expires: DEFAULT_ALLOW_RESPONSE_EXPIRATION,
  4244  	}
  4245  
  4246  	for k, v := range pm {
  4247  		tk, v = unwrapValue(v, &lt)
  4248  		switch strings.ToLower(k) {
  4249  		case "max", "max_msgs", "max_messages", "max_responses":
  4250  			max := int(v.(int64))
  4251  			// Negative values are accepted (mean infinite), and 0
  4252  			// means default value (set above).
  4253  			if max != 0 {
  4254  				rp.MaxMsgs = max
  4255  			}
  4256  		case "expires", "expiration", "ttl":
  4257  			wd, ok := v.(string)
  4258  			if ok {
  4259  				ttl, err := time.ParseDuration(wd)
  4260  				if err != nil {
  4261  					err := &configErr{tk, fmt.Sprintf("error parsing expires: %v", err)}
  4262  					*errors = append(*errors, err)
  4263  					return nil
  4264  				}
  4265  				// Negative values are accepted (mean infinite), and 0
  4266  				// means default value (set above).
  4267  				if ttl != 0 {
  4268  					rp.Expires = ttl
  4269  				}
  4270  			} else {
  4271  				err := &configErr{tk, "error parsing expires, not a duration string"}
  4272  				*errors = append(*errors, err)
  4273  				return nil
  4274  			}
  4275  		default:
  4276  			if !tk.IsUsedVariable() {
  4277  				err := &configErr{tk, fmt.Sprintf("Unknown field %q parsing permissions", k)}
  4278  				*errors = append(*errors, err)
  4279  			}
  4280  		}
  4281  	}
  4282  	return rp
  4283  }
  4284  
  4285  // Helper function to parse old style authorization configs.
  4286  func parseOldPermissionStyle(v interface{}, errors, warnings *[]error) (*SubjectPermission, error) {
  4287  	subjects, err := parsePermSubjects(v, errors, warnings)
  4288  	if err != nil {
  4289  		return nil, err
  4290  	}
  4291  	return &SubjectPermission{Allow: subjects}, nil
  4292  }
  4293  
  4294  // Helper function to parse new style authorization into a SubjectPermission with Allow and Deny.
  4295  func parseSubjectPermission(v interface{}, errors, warnings *[]error) (*SubjectPermission, error) {
  4296  	var lt token
  4297  	defer convertPanicToErrorList(&lt, errors)
  4298  
  4299  	m := v.(map[string]interface{})
  4300  	if len(m) == 0 {
  4301  		return nil, nil
  4302  	}
  4303  	p := &SubjectPermission{}
  4304  	for k, v := range m {
  4305  		tk, _ := unwrapValue(v, &lt)
  4306  		switch strings.ToLower(k) {
  4307  		case "allow":
  4308  			subjects, err := parsePermSubjects(tk, errors, warnings)
  4309  			if err != nil {
  4310  				*errors = append(*errors, err)
  4311  				continue
  4312  			}
  4313  			p.Allow = subjects
  4314  		case "deny":
  4315  			subjects, err := parsePermSubjects(tk, errors, warnings)
  4316  			if err != nil {
  4317  				*errors = append(*errors, err)
  4318  				continue
  4319  			}
  4320  			p.Deny = subjects
  4321  		default:
  4322  			if !tk.IsUsedVariable() {
  4323  				err := &configErr{tk, fmt.Sprintf("Unknown field name %q parsing subject permissions, only 'allow' or 'deny' are permitted", k)}
  4324  				*errors = append(*errors, err)
  4325  			}
  4326  		}
  4327  	}
  4328  	return p, nil
  4329  }
  4330  
  4331  // Helper function to validate permissions subjects.
  4332  func checkPermSubjectArray(sa []string) error {
  4333  	for _, s := range sa {
  4334  		if !IsValidSubject(s) {
  4335  			// Check here if this is a queue group qualified subject.
  4336  			elements := strings.Fields(s)
  4337  			if len(elements) != 2 {
  4338  				return fmt.Errorf("subject %q is not a valid subject", s)
  4339  			} else if !IsValidSubject(elements[0]) {
  4340  				return fmt.Errorf("subject %q is not a valid subject", elements[0])
  4341  			}
  4342  		}
  4343  	}
  4344  	return nil
  4345  }
  4346  
  4347  // PrintTLSHelpAndDie prints TLS usage and exits.
  4348  func PrintTLSHelpAndDie() {
  4349  	fmt.Printf("%s", tlsUsage)
  4350  	for k := range cipherMap {
  4351  		fmt.Printf("    %s\n", k)
  4352  	}
  4353  	fmt.Printf("\nAvailable curve preferences include:\n")
  4354  	for k := range curvePreferenceMap {
  4355  		fmt.Printf("    %s\n", k)
  4356  	}
  4357  	if runtime.GOOS == "windows" {
  4358  		fmt.Printf("%s\n", certstore.Usage)
  4359  	}
  4360  	fmt.Printf("%s", certidp.OCSPPeerUsage)
  4361  	fmt.Printf("%s", OCSPResponseCacheUsage)
  4362  	os.Exit(0)
  4363  }
  4364  
  4365  func parseCipher(cipherName string) (uint16, error) {
  4366  	cipher, exists := cipherMap[cipherName]
  4367  	if !exists {
  4368  		return 0, fmt.Errorf("unrecognized cipher %s", cipherName)
  4369  	}
  4370  
  4371  	return cipher, nil
  4372  }
  4373  
  4374  func parseCurvePreferences(curveName string) (tls.CurveID, error) {
  4375  	curve, exists := curvePreferenceMap[curveName]
  4376  	if !exists {
  4377  		return 0, fmt.Errorf("unrecognized curve preference %s", curveName)
  4378  	}
  4379  	return curve, nil
  4380  }
  4381  
  4382  // Helper function to parse TLS configs.
  4383  func parseTLS(v interface{}, isClientCtx bool) (t *TLSConfigOpts, retErr error) {
  4384  	var (
  4385  		tlsm map[string]interface{}
  4386  		tc   = TLSConfigOpts{}
  4387  		lt   token
  4388  	)
  4389  	defer convertPanicToError(&lt, &retErr)
  4390  
  4391  	tk, v := unwrapValue(v, &lt)
  4392  	tlsm = v.(map[string]interface{})
  4393  	for mk, mv := range tlsm {
  4394  		tk, mv := unwrapValue(mv, &lt)
  4395  		switch strings.ToLower(mk) {
  4396  		case "cert_file":
  4397  			certFile, ok := mv.(string)
  4398  			if !ok {
  4399  				return nil, &configErr{tk, "error parsing tls config, expected 'cert_file' to be filename"}
  4400  			}
  4401  			tc.CertFile = certFile
  4402  		case "key_file":
  4403  			keyFile, ok := mv.(string)
  4404  			if !ok {
  4405  				return nil, &configErr{tk, "error parsing tls config, expected 'key_file' to be filename"}
  4406  			}
  4407  			tc.KeyFile = keyFile
  4408  		case "ca_file":
  4409  			caFile, ok := mv.(string)
  4410  			if !ok {
  4411  				return nil, &configErr{tk, "error parsing tls config, expected 'ca_file' to be filename"}
  4412  			}
  4413  			tc.CaFile = caFile
  4414  		case "insecure":
  4415  			insecure, ok := mv.(bool)
  4416  			if !ok {
  4417  				return nil, &configErr{tk, "error parsing tls config, expected 'insecure' to be a boolean"}
  4418  			}
  4419  			tc.Insecure = insecure
  4420  		case "verify":
  4421  			verify, ok := mv.(bool)
  4422  			if !ok {
  4423  				return nil, &configErr{tk, "error parsing tls config, expected 'verify' to be a boolean"}
  4424  			}
  4425  			tc.Verify = verify
  4426  		case "verify_and_map":
  4427  			verify, ok := mv.(bool)
  4428  			if !ok {
  4429  				return nil, &configErr{tk, "error parsing tls config, expected 'verify_and_map' to be a boolean"}
  4430  			}
  4431  			if verify {
  4432  				tc.Verify = verify
  4433  			}
  4434  			tc.Map = verify
  4435  		case "verify_cert_and_check_known_urls":
  4436  			verify, ok := mv.(bool)
  4437  			if !ok {
  4438  				return nil, &configErr{tk, "error parsing tls config, expected 'verify_cert_and_check_known_urls' to be a boolean"}
  4439  			}
  4440  			if verify && isClientCtx {
  4441  				return nil, &configErr{tk, "verify_cert_and_check_known_urls not supported in this context"}
  4442  			}
  4443  			if verify {
  4444  				tc.Verify = verify
  4445  			}
  4446  			tc.TLSCheckKnownURLs = verify
  4447  		case "cipher_suites":
  4448  			ra := mv.([]interface{})
  4449  			if len(ra) == 0 {
  4450  				return nil, &configErr{tk, "error parsing tls config, 'cipher_suites' cannot be empty"}
  4451  			}
  4452  			tc.Ciphers = make([]uint16, 0, len(ra))
  4453  			for _, r := range ra {
  4454  				tk, r := unwrapValue(r, &lt)
  4455  				cipher, err := parseCipher(r.(string))
  4456  				if err != nil {
  4457  					return nil, &configErr{tk, err.Error()}
  4458  				}
  4459  				tc.Ciphers = append(tc.Ciphers, cipher)
  4460  			}
  4461  		case "curve_preferences":
  4462  			ra := mv.([]interface{})
  4463  			if len(ra) == 0 {
  4464  				return nil, &configErr{tk, "error parsing tls config, 'curve_preferences' cannot be empty"}
  4465  			}
  4466  			tc.CurvePreferences = make([]tls.CurveID, 0, len(ra))
  4467  			for _, r := range ra {
  4468  				tk, r := unwrapValue(r, &lt)
  4469  				cps, err := parseCurvePreferences(r.(string))
  4470  				if err != nil {
  4471  					return nil, &configErr{tk, err.Error()}
  4472  				}
  4473  				tc.CurvePreferences = append(tc.CurvePreferences, cps)
  4474  			}
  4475  		case "timeout":
  4476  			at := float64(0)
  4477  			switch mv := mv.(type) {
  4478  			case int64:
  4479  				at = float64(mv)
  4480  			case float64:
  4481  				at = mv
  4482  			case string:
  4483  				d, err := time.ParseDuration(mv)
  4484  				if err != nil {
  4485  					return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, 'timeout' %s", err)}
  4486  				}
  4487  				at = d.Seconds()
  4488  			default:
  4489  				return nil, &configErr{tk, "error parsing tls config, 'timeout' wrong type"}
  4490  			}
  4491  			tc.Timeout = at
  4492  		case "connection_rate_limit":
  4493  			at := int64(0)
  4494  			switch mv := mv.(type) {
  4495  			case int64:
  4496  				at = mv
  4497  			default:
  4498  				return nil, &configErr{tk, "error parsing tls config, 'connection_rate_limit' wrong type"}
  4499  			}
  4500  			tc.RateLimit = at
  4501  		case "pinned_certs":
  4502  			ra, ok := mv.([]interface{})
  4503  			if !ok {
  4504  				return nil, &configErr{tk, "error parsing tls config, expected 'pinned_certs' to be a list of hex-encoded sha256 of DER encoded SubjectPublicKeyInfo"}
  4505  			}
  4506  			if len(ra) != 0 {
  4507  				wl := PinnedCertSet{}
  4508  				re := regexp.MustCompile("^[A-Fa-f0-9]{64}$")
  4509  				for _, r := range ra {
  4510  					tk, r := unwrapValue(r, &lt)
  4511  					entry := strings.ToLower(r.(string))
  4512  					if !re.MatchString(entry) {
  4513  						return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, 'pinned_certs' key %s does not look like hex-encoded sha256 of DER encoded SubjectPublicKeyInfo", entry)}
  4514  					}
  4515  					wl[entry] = struct{}{}
  4516  				}
  4517  				tc.PinnedCerts = wl
  4518  			}
  4519  		case "cert_store":
  4520  			certStore, ok := mv.(string)
  4521  			if !ok || certStore == _EMPTY_ {
  4522  				return nil, &configErr{tk, certstore.ErrBadCertStoreField.Error()}
  4523  			}
  4524  			certStoreType, err := certstore.ParseCertStore(certStore)
  4525  			if err != nil {
  4526  				return nil, &configErr{tk, err.Error()}
  4527  			}
  4528  			tc.CertStore = certStoreType
  4529  		case "cert_match_by":
  4530  			certMatchBy, ok := mv.(string)
  4531  			if !ok || certMatchBy == _EMPTY_ {
  4532  				return nil, &configErr{tk, certstore.ErrBadCertMatchByField.Error()}
  4533  			}
  4534  			certMatchByType, err := certstore.ParseCertMatchBy(certMatchBy)
  4535  			if err != nil {
  4536  				return nil, &configErr{tk, err.Error()}
  4537  			}
  4538  			tc.CertMatchBy = certMatchByType
  4539  		case "cert_match":
  4540  			certMatch, ok := mv.(string)
  4541  			if !ok || certMatch == _EMPTY_ {
  4542  				return nil, &configErr{tk, certstore.ErrBadCertMatchField.Error()}
  4543  			}
  4544  			tc.CertMatch = certMatch
  4545  		case "handshake_first", "first", "immediate":
  4546  			switch mv := mv.(type) {
  4547  			case bool:
  4548  				tc.HandshakeFirst = mv
  4549  			case string:
  4550  				switch strings.ToLower(mv) {
  4551  				case "true", "on":
  4552  					tc.HandshakeFirst = true
  4553  				case "false", "off":
  4554  					tc.HandshakeFirst = false
  4555  				case "auto", "auto_fallback":
  4556  					tc.HandshakeFirst = true
  4557  					tc.FallbackDelay = DEFAULT_TLS_HANDSHAKE_FIRST_FALLBACK_DELAY
  4558  				default:
  4559  					// Check to see if this is a duration.
  4560  					if dur, err := time.ParseDuration(mv); err == nil {
  4561  						tc.HandshakeFirst = true
  4562  						tc.FallbackDelay = dur
  4563  						break
  4564  					}
  4565  					return nil, &configErr{tk, fmt.Sprintf("field %q's value %q is invalid", mk, mv)}
  4566  				}
  4567  			default:
  4568  				return nil, &configErr{tk, fmt.Sprintf("field %q should be a boolean or a string, got %T", mk, mv)}
  4569  			}
  4570  		case "ocsp_peer":
  4571  			switch vv := mv.(type) {
  4572  			case bool:
  4573  				pc := certidp.NewOCSPPeerConfig()
  4574  				if vv {
  4575  					// Set enabled
  4576  					pc.Verify = true
  4577  					tc.OCSPPeerConfig = pc
  4578  				} else {
  4579  					// Set disabled
  4580  					pc.Verify = false
  4581  					tc.OCSPPeerConfig = pc
  4582  				}
  4583  			case map[string]interface{}:
  4584  				pc, err := parseOCSPPeer(mv)
  4585  				if err != nil {
  4586  					return nil, &configErr{tk, err.Error()}
  4587  				}
  4588  				tc.OCSPPeerConfig = pc
  4589  			default:
  4590  				return nil, &configErr{tk, fmt.Sprintf("error parsing ocsp peer config: unsupported type %T", v)}
  4591  			}
  4592  		case "certs", "certificates":
  4593  			certs, ok := mv.([]interface{})
  4594  			if !ok {
  4595  				return nil, &configErr{tk, fmt.Sprintf("error parsing certificates config: unsupported type %T", v)}
  4596  			}
  4597  			tc.Certificates = make([]*TLSCertPairOpt, len(certs))
  4598  			for i, v := range certs {
  4599  				tk, vv := unwrapValue(v, &lt)
  4600  				pair, ok := vv.(map[string]interface{})
  4601  				if !ok {
  4602  					return nil, &configErr{tk, fmt.Sprintf("error parsing certificates config: unsupported type %T", vv)}
  4603  				}
  4604  				certPair := &TLSCertPairOpt{}
  4605  				for k, v := range pair {
  4606  					tk, vv = unwrapValue(v, &lt)
  4607  					file, ok := vv.(string)
  4608  					if !ok {
  4609  						return nil, &configErr{tk, fmt.Sprintf("error parsing certificates config: unsupported type %T", vv)}
  4610  					}
  4611  					switch k {
  4612  					case "cert_file":
  4613  						certPair.CertFile = file
  4614  					case "key_file":
  4615  						certPair.KeyFile = file
  4616  					default:
  4617  						return nil, &configErr{tk, fmt.Sprintf("error parsing tls certs config, unknown field %q", k)}
  4618  					}
  4619  				}
  4620  				if certPair.CertFile == _EMPTY_ || certPair.KeyFile == _EMPTY_ {
  4621  					return nil, &configErr{tk, "error parsing certificates config: both 'cert_file' and 'cert_key' options are required"}
  4622  				}
  4623  				tc.Certificates[i] = certPair
  4624  			}
  4625  		default:
  4626  			return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, unknown field %q", mk)}
  4627  		}
  4628  	}
  4629  	if len(tc.Certificates) > 0 && tc.CertFile != _EMPTY_ {
  4630  		return nil, &configErr{tk, "error parsing tls config, cannot combine 'cert_file' option with 'certs' option"}
  4631  	}
  4632  
  4633  	// If cipher suites were not specified then use the defaults
  4634  	if tc.Ciphers == nil {
  4635  		tc.Ciphers = defaultCipherSuites()
  4636  	}
  4637  
  4638  	// If curve preferences were not specified, then use the defaults
  4639  	if tc.CurvePreferences == nil {
  4640  		tc.CurvePreferences = defaultCurvePreferences()
  4641  	}
  4642  
  4643  	return &tc, nil
  4644  }
  4645  
  4646  func parseSimpleAuth(v interface{}, errors *[]error, warnings *[]error) *authorization {
  4647  	var (
  4648  		am   map[string]interface{}
  4649  		tk   token
  4650  		lt   token
  4651  		auth = &authorization{}
  4652  	)
  4653  	defer convertPanicToErrorList(&lt, errors)
  4654  
  4655  	_, v = unwrapValue(v, &lt)
  4656  	am = v.(map[string]interface{})
  4657  	for mk, mv := range am {
  4658  		tk, mv = unwrapValue(mv, &lt)
  4659  		switch strings.ToLower(mk) {
  4660  		case "user", "username":
  4661  			auth.user = mv.(string)
  4662  		case "pass", "password":
  4663  			auth.pass = mv.(string)
  4664  		case "token":
  4665  			auth.token = mv.(string)
  4666  		case "timeout":
  4667  			at := float64(1)
  4668  			switch mv := mv.(type) {
  4669  			case int64:
  4670  				at = float64(mv)
  4671  			case float64:
  4672  				at = mv
  4673  			}
  4674  			auth.timeout = at
  4675  		default:
  4676  			if !tk.IsUsedVariable() {
  4677  				err := &unknownConfigFieldErr{
  4678  					field: mk,
  4679  					configErr: configErr{
  4680  						token: tk,
  4681  					},
  4682  				}
  4683  				*errors = append(*errors, err)
  4684  			}
  4685  			continue
  4686  		}
  4687  	}
  4688  	return auth
  4689  }
  4690  
  4691  func parseStringArray(fieldName string, tk token, lt *token, mv interface{}, errors *[]error, warnings *[]error) ([]string, error) {
  4692  	switch mv := mv.(type) {
  4693  	case string:
  4694  		return []string{mv}, nil
  4695  	case []interface{}:
  4696  		strs := make([]string, 0, len(mv))
  4697  		for _, val := range mv {
  4698  			tk, val = unwrapValue(val, lt)
  4699  			if str, ok := val.(string); ok {
  4700  				strs = append(strs, str)
  4701  			} else {
  4702  				err := &configErr{tk, fmt.Sprintf("error parsing %s: unsupported type in array %T", fieldName, val)}
  4703  				*errors = append(*errors, err)
  4704  				continue
  4705  			}
  4706  		}
  4707  		return strs, nil
  4708  	default:
  4709  		err := &configErr{tk, fmt.Sprintf("error parsing %s: unsupported type %T", fieldName, mv)}
  4710  		*errors = append(*errors, err)
  4711  		return nil, err
  4712  	}
  4713  }
  4714  
  4715  func parseWebsocket(v interface{}, o *Options, errors *[]error, warnings *[]error) error {
  4716  	var lt token
  4717  	defer convertPanicToErrorList(&lt, errors)
  4718  
  4719  	tk, v := unwrapValue(v, &lt)
  4720  	gm, ok := v.(map[string]interface{})
  4721  	if !ok {
  4722  		return &configErr{tk, fmt.Sprintf("Expected websocket to be a map, got %T", v)}
  4723  	}
  4724  	for mk, mv := range gm {
  4725  		// Again, unwrap token value if line check is required.
  4726  		tk, mv = unwrapValue(mv, &lt)
  4727  		switch strings.ToLower(mk) {
  4728  		case "listen":
  4729  			hp, err := parseListen(mv)
  4730  			if err != nil {
  4731  				err := &configErr{tk, err.Error()}
  4732  				*errors = append(*errors, err)
  4733  				continue
  4734  			}
  4735  			o.Websocket.Host = hp.host
  4736  			o.Websocket.Port = hp.port
  4737  		case "port":
  4738  			o.Websocket.Port = int(mv.(int64))
  4739  		case "host", "net":
  4740  			o.Websocket.Host = mv.(string)
  4741  		case "advertise":
  4742  			o.Websocket.Advertise = mv.(string)
  4743  		case "no_tls":
  4744  			o.Websocket.NoTLS = mv.(bool)
  4745  		case "tls":
  4746  			tc, err := parseTLS(tk, true)
  4747  			if err != nil {
  4748  				*errors = append(*errors, err)
  4749  				continue
  4750  			}
  4751  			if o.Websocket.TLSConfig, err = GenTLSConfig(tc); err != nil {
  4752  				err := &configErr{tk, err.Error()}
  4753  				*errors = append(*errors, err)
  4754  				continue
  4755  			}
  4756  			o.Websocket.TLSMap = tc.Map
  4757  			o.Websocket.TLSPinnedCerts = tc.PinnedCerts
  4758  			o.Websocket.tlsConfigOpts = tc
  4759  		case "same_origin":
  4760  			o.Websocket.SameOrigin = mv.(bool)
  4761  		case "allowed_origins", "allowed_origin", "allow_origins", "allow_origin", "origins", "origin":
  4762  			o.Websocket.AllowedOrigins, _ = parseStringArray("allowed origins", tk, &lt, mv, errors, warnings)
  4763  		case "handshake_timeout":
  4764  			ht := time.Duration(0)
  4765  			switch mv := mv.(type) {
  4766  			case int64:
  4767  				ht = time.Duration(mv) * time.Second
  4768  			case string:
  4769  				var err error
  4770  				ht, err = time.ParseDuration(mv)
  4771  				if err != nil {
  4772  					err := &configErr{tk, err.Error()}
  4773  					*errors = append(*errors, err)
  4774  					continue
  4775  				}
  4776  			default:
  4777  				err := &configErr{tk, fmt.Sprintf("error parsing handshake timeout: unsupported type %T", mv)}
  4778  				*errors = append(*errors, err)
  4779  			}
  4780  			o.Websocket.HandshakeTimeout = ht
  4781  		case "compress", "compression":
  4782  			o.Websocket.Compression = mv.(bool)
  4783  		case "authorization", "authentication":
  4784  			auth := parseSimpleAuth(tk, errors, warnings)
  4785  			o.Websocket.Username = auth.user
  4786  			o.Websocket.Password = auth.pass
  4787  			o.Websocket.Token = auth.token
  4788  			o.Websocket.AuthTimeout = auth.timeout
  4789  		case "jwt_cookie":
  4790  			o.Websocket.JWTCookie = mv.(string)
  4791  		case "user_cookie":
  4792  			o.Websocket.UsernameCookie = mv.(string)
  4793  		case "pass_cookie":
  4794  			o.Websocket.PasswordCookie = mv.(string)
  4795  		case "token_cookie":
  4796  			o.Websocket.TokenCookie = mv.(string)
  4797  		case "no_auth_user":
  4798  			o.Websocket.NoAuthUser = mv.(string)
  4799  		default:
  4800  			if !tk.IsUsedVariable() {
  4801  				err := &unknownConfigFieldErr{
  4802  					field: mk,
  4803  					configErr: configErr{
  4804  						token: tk,
  4805  					},
  4806  				}
  4807  				*errors = append(*errors, err)
  4808  				continue
  4809  			}
  4810  		}
  4811  	}
  4812  	return nil
  4813  }
  4814  
  4815  func parseMQTT(v interface{}, o *Options, errors *[]error, warnings *[]error) error {
  4816  	var lt token
  4817  	defer convertPanicToErrorList(&lt, errors)
  4818  
  4819  	tk, v := unwrapValue(v, &lt)
  4820  	gm, ok := v.(map[string]interface{})
  4821  	if !ok {
  4822  		return &configErr{tk, fmt.Sprintf("Expected mqtt to be a map, got %T", v)}
  4823  	}
  4824  	for mk, mv := range gm {
  4825  		// Again, unwrap token value if line check is required.
  4826  		tk, mv = unwrapValue(mv, &lt)
  4827  		switch strings.ToLower(mk) {
  4828  		case "listen":
  4829  			hp, err := parseListen(mv)
  4830  			if err != nil {
  4831  				err := &configErr{tk, err.Error()}
  4832  				*errors = append(*errors, err)
  4833  				continue
  4834  			}
  4835  			o.MQTT.Host = hp.host
  4836  			o.MQTT.Port = hp.port
  4837  		case "port":
  4838  			o.MQTT.Port = int(mv.(int64))
  4839  		case "host", "net":
  4840  			o.MQTT.Host = mv.(string)
  4841  		case "tls":
  4842  			tc, err := parseTLS(tk, true)
  4843  			if err != nil {
  4844  				*errors = append(*errors, err)
  4845  				continue
  4846  			}
  4847  			if o.MQTT.TLSConfig, err = GenTLSConfig(tc); err != nil {
  4848  				err := &configErr{tk, err.Error()}
  4849  				*errors = append(*errors, err)
  4850  				continue
  4851  			}
  4852  			o.MQTT.TLSTimeout = tc.Timeout
  4853  			o.MQTT.TLSMap = tc.Map
  4854  			o.MQTT.TLSPinnedCerts = tc.PinnedCerts
  4855  			o.MQTT.tlsConfigOpts = tc
  4856  		case "authorization", "authentication":
  4857  			auth := parseSimpleAuth(tk, errors, warnings)
  4858  			o.MQTT.Username = auth.user
  4859  			o.MQTT.Password = auth.pass
  4860  			o.MQTT.Token = auth.token
  4861  			o.MQTT.AuthTimeout = auth.timeout
  4862  		case "no_auth_user":
  4863  			o.MQTT.NoAuthUser = mv.(string)
  4864  		case "ack_wait", "ackwait":
  4865  			o.MQTT.AckWait = parseDuration("ack_wait", tk, mv, errors, warnings)
  4866  		case "max_ack_pending", "max_pending", "max_inflight":
  4867  			tmp := int(mv.(int64))
  4868  			if tmp < 0 || tmp > 0xFFFF {
  4869  				err := &configErr{tk, fmt.Sprintf("invalid value %v, should in [0..%d] range", tmp, 0xFFFF)}
  4870  				*errors = append(*errors, err)
  4871  			} else {
  4872  				o.MQTT.MaxAckPending = uint16(tmp)
  4873  			}
  4874  		case "js_domain":
  4875  			o.MQTT.JsDomain = mv.(string)
  4876  		case "stream_replicas":
  4877  			o.MQTT.StreamReplicas = int(mv.(int64))
  4878  		case "consumer_replicas":
  4879  			err := &configWarningErr{
  4880  				field: mk,
  4881  				configErr: configErr{
  4882  					token:  tk,
  4883  					reason: `consumer replicas setting ignored in this server version`,
  4884  				},
  4885  			}
  4886  			*warnings = append(*warnings, err)
  4887  		case "consumer_memory_storage":
  4888  			o.MQTT.ConsumerMemoryStorage = mv.(bool)
  4889  		case "consumer_inactive_threshold", "consumer_auto_cleanup":
  4890  			o.MQTT.ConsumerInactiveThreshold = parseDuration("consumer_inactive_threshold", tk, mv, errors, warnings)
  4891  
  4892  		case "reject_qos2_publish":
  4893  			o.MQTT.rejectQoS2Pub = mv.(bool)
  4894  		case "downgrade_qos2_subscribe":
  4895  			o.MQTT.downgradeQoS2Sub = mv.(bool)
  4896  
  4897  		default:
  4898  			if !tk.IsUsedVariable() {
  4899  				err := &unknownConfigFieldErr{
  4900  					field: mk,
  4901  					configErr: configErr{
  4902  						token: tk,
  4903  					},
  4904  				}
  4905  				*errors = append(*errors, err)
  4906  				continue
  4907  			}
  4908  		}
  4909  	}
  4910  	return nil
  4911  }
  4912  
  4913  // GenTLSConfig loads TLS related configuration parameters.
  4914  func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) {
  4915  	// Create the tls.Config from our options before including the certs.
  4916  	// It will determine the cipher suites that we prefer.
  4917  	// FIXME(dlc) change if ARM based.
  4918  	config := tls.Config{
  4919  		MinVersion:               tls.VersionTLS12,
  4920  		CipherSuites:             tc.Ciphers,
  4921  		PreferServerCipherSuites: true,
  4922  		CurvePreferences:         tc.CurvePreferences,
  4923  		InsecureSkipVerify:       tc.Insecure,
  4924  	}
  4925  
  4926  	switch {
  4927  	case tc.CertFile != _EMPTY_ && tc.CertStore != certstore.STOREEMPTY:
  4928  		return nil, certstore.ErrConflictCertFileAndStore
  4929  	case tc.CertFile != _EMPTY_ && tc.KeyFile == _EMPTY_:
  4930  		return nil, fmt.Errorf("missing 'key_file' in TLS configuration")
  4931  	case tc.CertFile == _EMPTY_ && tc.KeyFile != _EMPTY_:
  4932  		return nil, fmt.Errorf("missing 'cert_file' in TLS configuration")
  4933  	case tc.CertFile != _EMPTY_ && tc.KeyFile != _EMPTY_:
  4934  		// Now load in cert and private key
  4935  		cert, err := tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile)
  4936  		if err != nil {
  4937  			return nil, fmt.Errorf("error parsing X509 certificate/key pair: %v", err)
  4938  		}
  4939  		cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
  4940  		if err != nil {
  4941  			return nil, fmt.Errorf("error parsing certificate: %v", err)
  4942  		}
  4943  		config.Certificates = []tls.Certificate{cert}
  4944  	case tc.CertStore != certstore.STOREEMPTY:
  4945  		err := certstore.TLSConfig(tc.CertStore, tc.CertMatchBy, tc.CertMatch, &config)
  4946  		if err != nil {
  4947  			return nil, err
  4948  		}
  4949  	case tc.Certificates != nil:
  4950  		// Multiple certificate support.
  4951  		config.Certificates = make([]tls.Certificate, len(tc.Certificates))
  4952  		for i, certPair := range tc.Certificates {
  4953  			cert, err := tls.LoadX509KeyPair(certPair.CertFile, certPair.KeyFile)
  4954  			if err != nil {
  4955  				return nil, fmt.Errorf("error parsing X509 certificate/key pair %d/%d: %v", i+1, len(tc.Certificates), err)
  4956  			}
  4957  			cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
  4958  			if err != nil {
  4959  				return nil, fmt.Errorf("error parsing certificate %d/%d: %v", i+1, len(tc.Certificates), err)
  4960  			}
  4961  			config.Certificates[i] = cert
  4962  		}
  4963  	}
  4964  
  4965  	// Require client certificates as needed
  4966  	if tc.Verify {
  4967  		config.ClientAuth = tls.RequireAndVerifyClientCert
  4968  	}
  4969  	// Add in CAs if applicable.
  4970  	if tc.CaFile != _EMPTY_ {
  4971  		rootPEM, err := os.ReadFile(tc.CaFile)
  4972  		if err != nil || rootPEM == nil {
  4973  			return nil, err
  4974  		}
  4975  		pool := x509.NewCertPool()
  4976  		ok := pool.AppendCertsFromPEM(rootPEM)
  4977  		if !ok {
  4978  			return nil, fmt.Errorf("failed to parse root ca certificate")
  4979  		}
  4980  		config.ClientCAs = pool
  4981  	}
  4982  
  4983  	return &config, nil
  4984  }
  4985  
  4986  // MergeOptions will merge two options giving preference to the flagOpts
  4987  // if the item is present.
  4988  func MergeOptions(fileOpts, flagOpts *Options) *Options {
  4989  	if fileOpts == nil {
  4990  		return flagOpts
  4991  	}
  4992  	if flagOpts == nil {
  4993  		return fileOpts
  4994  	}
  4995  	// Merge the two, flagOpts override
  4996  	opts := *fileOpts
  4997  
  4998  	if flagOpts.Port != 0 {
  4999  		opts.Port = flagOpts.Port
  5000  	}
  5001  	if flagOpts.Host != _EMPTY_ {
  5002  		opts.Host = flagOpts.Host
  5003  	}
  5004  	if flagOpts.DontListen {
  5005  		opts.DontListen = flagOpts.DontListen
  5006  	}
  5007  	if flagOpts.ClientAdvertise != _EMPTY_ {
  5008  		opts.ClientAdvertise = flagOpts.ClientAdvertise
  5009  	}
  5010  	if flagOpts.Username != _EMPTY_ {
  5011  		opts.Username = flagOpts.Username
  5012  	}
  5013  	if flagOpts.Password != _EMPTY_ {
  5014  		opts.Password = flagOpts.Password
  5015  	}
  5016  	if flagOpts.Authorization != _EMPTY_ {
  5017  		opts.Authorization = flagOpts.Authorization
  5018  	}
  5019  	if flagOpts.HTTPPort != 0 {
  5020  		opts.HTTPPort = flagOpts.HTTPPort
  5021  	}
  5022  	if flagOpts.HTTPBasePath != _EMPTY_ {
  5023  		opts.HTTPBasePath = flagOpts.HTTPBasePath
  5024  	}
  5025  	if flagOpts.Debug {
  5026  		opts.Debug = true
  5027  	}
  5028  	if flagOpts.Trace {
  5029  		opts.Trace = true
  5030  	}
  5031  	if flagOpts.Logtime {
  5032  		opts.Logtime = true
  5033  	}
  5034  	if flagOpts.LogFile != _EMPTY_ {
  5035  		opts.LogFile = flagOpts.LogFile
  5036  	}
  5037  	if flagOpts.PidFile != _EMPTY_ {
  5038  		opts.PidFile = flagOpts.PidFile
  5039  	}
  5040  	if flagOpts.PortsFileDir != _EMPTY_ {
  5041  		opts.PortsFileDir = flagOpts.PortsFileDir
  5042  	}
  5043  	if flagOpts.ProfPort != 0 {
  5044  		opts.ProfPort = flagOpts.ProfPort
  5045  	}
  5046  	if flagOpts.Cluster.ListenStr != _EMPTY_ {
  5047  		opts.Cluster.ListenStr = flagOpts.Cluster.ListenStr
  5048  	}
  5049  	if flagOpts.Cluster.NoAdvertise {
  5050  		opts.Cluster.NoAdvertise = true
  5051  	}
  5052  	if flagOpts.Cluster.ConnectRetries != 0 {
  5053  		opts.Cluster.ConnectRetries = flagOpts.Cluster.ConnectRetries
  5054  	}
  5055  	if flagOpts.Cluster.Advertise != _EMPTY_ {
  5056  		opts.Cluster.Advertise = flagOpts.Cluster.Advertise
  5057  	}
  5058  	if flagOpts.RoutesStr != _EMPTY_ {
  5059  		mergeRoutes(&opts, flagOpts)
  5060  	}
  5061  	if flagOpts.JetStream {
  5062  		fileOpts.JetStream = flagOpts.JetStream
  5063  	}
  5064  	return &opts
  5065  }
  5066  
  5067  // RoutesFromStr parses route URLs from a string
  5068  func RoutesFromStr(routesStr string) []*url.URL {
  5069  	routes := strings.Split(routesStr, ",")
  5070  	if len(routes) == 0 {
  5071  		return nil
  5072  	}
  5073  	routeUrls := []*url.URL{}
  5074  	for _, r := range routes {
  5075  		r = strings.TrimSpace(r)
  5076  		u, _ := url.Parse(r)
  5077  		routeUrls = append(routeUrls, u)
  5078  	}
  5079  	return routeUrls
  5080  }
  5081  
  5082  // This will merge the flag routes and override anything that was present.
  5083  func mergeRoutes(opts, flagOpts *Options) {
  5084  	routeUrls := RoutesFromStr(flagOpts.RoutesStr)
  5085  	if routeUrls == nil {
  5086  		return
  5087  	}
  5088  	opts.Routes = routeUrls
  5089  	opts.RoutesStr = flagOpts.RoutesStr
  5090  }
  5091  
  5092  // RemoveSelfReference removes this server from an array of routes
  5093  func RemoveSelfReference(clusterPort int, routes []*url.URL) ([]*url.URL, error) {
  5094  	var cleanRoutes []*url.URL
  5095  	cport := strconv.Itoa(clusterPort)
  5096  
  5097  	selfIPs, err := getInterfaceIPs()
  5098  	if err != nil {
  5099  		return nil, err
  5100  	}
  5101  	for _, r := range routes {
  5102  		host, port, err := net.SplitHostPort(r.Host)
  5103  		if err != nil {
  5104  			return nil, err
  5105  		}
  5106  
  5107  		ipList, err := getURLIP(host)
  5108  		if err != nil {
  5109  			return nil, err
  5110  		}
  5111  		if cport == port && isIPInList(selfIPs, ipList) {
  5112  			continue
  5113  		}
  5114  		cleanRoutes = append(cleanRoutes, r)
  5115  	}
  5116  
  5117  	return cleanRoutes, nil
  5118  }
  5119  
  5120  func isIPInList(list1 []net.IP, list2 []net.IP) bool {
  5121  	for _, ip1 := range list1 {
  5122  		for _, ip2 := range list2 {
  5123  			if ip1.Equal(ip2) {
  5124  				return true
  5125  			}
  5126  		}
  5127  	}
  5128  	return false
  5129  }
  5130  
  5131  func getURLIP(ipStr string) ([]net.IP, error) {
  5132  	ipList := []net.IP{}
  5133  
  5134  	ip := net.ParseIP(ipStr)
  5135  	if ip != nil {
  5136  		ipList = append(ipList, ip)
  5137  		return ipList, nil
  5138  	}
  5139  
  5140  	hostAddr, err := net.LookupHost(ipStr)
  5141  	if err != nil {
  5142  		return nil, fmt.Errorf("Error looking up host with route hostname: %v", err)
  5143  	}
  5144  	for _, addr := range hostAddr {
  5145  		ip = net.ParseIP(addr)
  5146  		if ip != nil {
  5147  			ipList = append(ipList, ip)
  5148  		}
  5149  	}
  5150  	return ipList, nil
  5151  }
  5152  
  5153  func getInterfaceIPs() ([]net.IP, error) {
  5154  	var localIPs []net.IP
  5155  
  5156  	interfaceAddr, err := net.InterfaceAddrs()
  5157  	if err != nil {
  5158  		return nil, fmt.Errorf("Error getting self referencing address: %v", err)
  5159  	}
  5160  
  5161  	for i := 0; i < len(interfaceAddr); i++ {
  5162  		interfaceIP, _, _ := net.ParseCIDR(interfaceAddr[i].String())
  5163  		if net.ParseIP(interfaceIP.String()) != nil {
  5164  			localIPs = append(localIPs, interfaceIP)
  5165  		} else {
  5166  			return nil, fmt.Errorf("Error parsing self referencing address: %v", err)
  5167  		}
  5168  	}
  5169  	return localIPs, nil
  5170  }
  5171  
  5172  func setBaselineOptions(opts *Options) {
  5173  	// Setup non-standard Go defaults
  5174  	if opts.Host == _EMPTY_ {
  5175  		opts.Host = DEFAULT_HOST
  5176  	}
  5177  	if opts.HTTPHost == _EMPTY_ {
  5178  		// Default to same bind from server if left undefined
  5179  		opts.HTTPHost = opts.Host
  5180  	}
  5181  	if opts.Port == 0 {
  5182  		opts.Port = DEFAULT_PORT
  5183  	} else if opts.Port == RANDOM_PORT {
  5184  		// Choose randomly inside of net.Listen
  5185  		opts.Port = 0
  5186  	}
  5187  	if opts.MaxConn == 0 {
  5188  		opts.MaxConn = DEFAULT_MAX_CONNECTIONS
  5189  	}
  5190  	if opts.PingInterval == 0 {
  5191  		opts.PingInterval = DEFAULT_PING_INTERVAL
  5192  	}
  5193  	if opts.MaxPingsOut == 0 {
  5194  		opts.MaxPingsOut = DEFAULT_PING_MAX_OUT
  5195  	}
  5196  	if opts.TLSTimeout == 0 {
  5197  		opts.TLSTimeout = float64(TLS_TIMEOUT) / float64(time.Second)
  5198  	}
  5199  	if opts.AuthTimeout == 0 {
  5200  		opts.AuthTimeout = getDefaultAuthTimeout(opts.TLSConfig, opts.TLSTimeout)
  5201  	}
  5202  	if opts.Cluster.Port != 0 || opts.Cluster.ListenStr != _EMPTY_ {
  5203  		if opts.Cluster.Host == _EMPTY_ {
  5204  			opts.Cluster.Host = DEFAULT_HOST
  5205  		}
  5206  		if opts.Cluster.TLSTimeout == 0 {
  5207  			opts.Cluster.TLSTimeout = float64(TLS_TIMEOUT) / float64(time.Second)
  5208  		}
  5209  		if opts.Cluster.AuthTimeout == 0 {
  5210  			opts.Cluster.AuthTimeout = getDefaultAuthTimeout(opts.Cluster.TLSConfig, opts.Cluster.TLSTimeout)
  5211  		}
  5212  		if opts.Cluster.PoolSize == 0 {
  5213  			opts.Cluster.PoolSize = DEFAULT_ROUTE_POOL_SIZE
  5214  		}
  5215  		// Unless pooling/accounts are disabled (by PoolSize being set to -1),
  5216  		// check for Cluster.Accounts. Add the system account if not present and
  5217  		// unless we have a configuration that disabled it.
  5218  		if opts.Cluster.PoolSize > 0 {
  5219  			sysAccName := opts.SystemAccount
  5220  			if sysAccName == _EMPTY_ && !opts.NoSystemAccount {
  5221  				sysAccName = DEFAULT_SYSTEM_ACCOUNT
  5222  			}
  5223  			if sysAccName != _EMPTY_ {
  5224  				var found bool
  5225  				for _, acc := range opts.Cluster.PinnedAccounts {
  5226  					if acc == sysAccName {
  5227  						found = true
  5228  						break
  5229  					}
  5230  				}
  5231  				if !found {
  5232  					opts.Cluster.PinnedAccounts = append(opts.Cluster.PinnedAccounts, sysAccName)
  5233  				}
  5234  			}
  5235  		}
  5236  		// Default to compression "accept", which means that compression is not
  5237  		// initiated, but if the remote selects compression, this server will
  5238  		// use the same.
  5239  		if c := &opts.Cluster.Compression; c.Mode == _EMPTY_ {
  5240  			if testDefaultClusterCompression != _EMPTY_ {
  5241  				c.Mode = testDefaultClusterCompression
  5242  			} else {
  5243  				c.Mode = CompressionAccept
  5244  			}
  5245  		}
  5246  	}
  5247  	if opts.LeafNode.Port != 0 {
  5248  		if opts.LeafNode.Host == _EMPTY_ {
  5249  			opts.LeafNode.Host = DEFAULT_HOST
  5250  		}
  5251  		if opts.LeafNode.TLSTimeout == 0 {
  5252  			opts.LeafNode.TLSTimeout = float64(TLS_TIMEOUT) / float64(time.Second)
  5253  		}
  5254  		if opts.LeafNode.AuthTimeout == 0 {
  5255  			opts.LeafNode.AuthTimeout = getDefaultAuthTimeout(opts.LeafNode.TLSConfig, opts.LeafNode.TLSTimeout)
  5256  		}
  5257  		// Default to compression "s2_auto".
  5258  		if c := &opts.LeafNode.Compression; c.Mode == _EMPTY_ {
  5259  			if testDefaultLeafNodeCompression != _EMPTY_ {
  5260  				c.Mode = testDefaultLeafNodeCompression
  5261  			} else {
  5262  				c.Mode = CompressionS2Auto
  5263  			}
  5264  		}
  5265  	}
  5266  	// Set baseline connect port for remotes.
  5267  	for _, r := range opts.LeafNode.Remotes {
  5268  		if r != nil {
  5269  			for _, u := range r.URLs {
  5270  				if u.Port() == _EMPTY_ {
  5271  					u.Host = net.JoinHostPort(u.Host, strconv.Itoa(DEFAULT_LEAFNODE_PORT))
  5272  				}
  5273  			}
  5274  			// Default to compression "s2_auto".
  5275  			if c := &r.Compression; c.Mode == _EMPTY_ {
  5276  				if testDefaultLeafNodeCompression != _EMPTY_ {
  5277  					c.Mode = testDefaultLeafNodeCompression
  5278  				} else {
  5279  					c.Mode = CompressionS2Auto
  5280  				}
  5281  			}
  5282  		}
  5283  	}
  5284  
  5285  	// Set this regardless of opts.LeafNode.Port
  5286  	if opts.LeafNode.ReconnectInterval == 0 {
  5287  		opts.LeafNode.ReconnectInterval = DEFAULT_LEAF_NODE_RECONNECT
  5288  	}
  5289  
  5290  	if opts.MaxControlLine == 0 {
  5291  		opts.MaxControlLine = MAX_CONTROL_LINE_SIZE
  5292  	}
  5293  	if opts.MaxPayload == 0 {
  5294  		opts.MaxPayload = MAX_PAYLOAD_SIZE
  5295  	}
  5296  	if opts.MaxPending == 0 {
  5297  		opts.MaxPending = MAX_PENDING_SIZE
  5298  	}
  5299  	if opts.WriteDeadline == time.Duration(0) {
  5300  		opts.WriteDeadline = DEFAULT_FLUSH_DEADLINE
  5301  	}
  5302  	if opts.MaxClosedClients == 0 {
  5303  		opts.MaxClosedClients = DEFAULT_MAX_CLOSED_CLIENTS
  5304  	}
  5305  	if opts.LameDuckDuration == 0 {
  5306  		opts.LameDuckDuration = DEFAULT_LAME_DUCK_DURATION
  5307  	}
  5308  	if opts.LameDuckGracePeriod == 0 {
  5309  		opts.LameDuckGracePeriod = DEFAULT_LAME_DUCK_GRACE_PERIOD
  5310  	}
  5311  	if opts.Gateway.Port != 0 {
  5312  		if opts.Gateway.Host == _EMPTY_ {
  5313  			opts.Gateway.Host = DEFAULT_HOST
  5314  		}
  5315  		if opts.Gateway.TLSTimeout == 0 {
  5316  			opts.Gateway.TLSTimeout = float64(TLS_TIMEOUT) / float64(time.Second)
  5317  		}
  5318  		if opts.Gateway.AuthTimeout == 0 {
  5319  			opts.Gateway.AuthTimeout = getDefaultAuthTimeout(opts.Gateway.TLSConfig, opts.Gateway.TLSTimeout)
  5320  		}
  5321  	}
  5322  	if opts.ConnectErrorReports == 0 {
  5323  		opts.ConnectErrorReports = DEFAULT_CONNECT_ERROR_REPORTS
  5324  	}
  5325  	if opts.ReconnectErrorReports == 0 {
  5326  		opts.ReconnectErrorReports = DEFAULT_RECONNECT_ERROR_REPORTS
  5327  	}
  5328  	if opts.Websocket.Port != 0 {
  5329  		if opts.Websocket.Host == _EMPTY_ {
  5330  			opts.Websocket.Host = DEFAULT_HOST
  5331  		}
  5332  	}
  5333  	if opts.MQTT.Port != 0 {
  5334  		if opts.MQTT.Host == _EMPTY_ {
  5335  			opts.MQTT.Host = DEFAULT_HOST
  5336  		}
  5337  		if opts.MQTT.TLSTimeout == 0 {
  5338  			opts.MQTT.TLSTimeout = float64(TLS_TIMEOUT) / float64(time.Second)
  5339  		}
  5340  	}
  5341  	// JetStream
  5342  	if opts.JetStreamMaxMemory == 0 && !opts.maxMemSet {
  5343  		opts.JetStreamMaxMemory = -1
  5344  	}
  5345  	if opts.JetStreamMaxStore == 0 && !opts.maxStoreSet {
  5346  		opts.JetStreamMaxStore = -1
  5347  	}
  5348  	if opts.SyncInterval == 0 && !opts.syncSet {
  5349  		opts.SyncInterval = defaultSyncInterval
  5350  	}
  5351  }
  5352  
  5353  func getDefaultAuthTimeout(tls *tls.Config, tlsTimeout float64) float64 {
  5354  	var authTimeout float64
  5355  	if tls != nil {
  5356  		authTimeout = tlsTimeout + 1.0
  5357  	} else {
  5358  		authTimeout = float64(AUTH_TIMEOUT / time.Second)
  5359  	}
  5360  	return authTimeout
  5361  }
  5362  
  5363  // ConfigureOptions accepts a flag set and augments it with NATS Server
  5364  // specific flags. On success, an options structure is returned configured
  5365  // based on the selected flags and/or configuration file.
  5366  // The command line options take precedence to the ones in the configuration file.
  5367  func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, printTLSHelp func()) (*Options, error) {
  5368  	opts := &Options{}
  5369  	var (
  5370  		showVersion            bool
  5371  		showHelp               bool
  5372  		showTLSHelp            bool
  5373  		signal                 string
  5374  		configFile             string
  5375  		dbgAndTrace            bool
  5376  		trcAndVerboseTrc       bool
  5377  		dbgAndTrcAndVerboseTrc bool
  5378  		err                    error
  5379  	)
  5380  
  5381  	fs.BoolVar(&showHelp, "h", false, "Show this message.")
  5382  	fs.BoolVar(&showHelp, "help", false, "Show this message.")
  5383  	fs.IntVar(&opts.Port, "port", 0, "Port to listen on.")
  5384  	fs.IntVar(&opts.Port, "p", 0, "Port to listen on.")
  5385  	fs.StringVar(&opts.ServerName, "n", _EMPTY_, "Server name.")
  5386  	fs.StringVar(&opts.ServerName, "name", _EMPTY_, "Server name.")
  5387  	fs.StringVar(&opts.ServerName, "server_name", _EMPTY_, "Server name.")
  5388  	fs.StringVar(&opts.Host, "addr", _EMPTY_, "Network host to listen on.")
  5389  	fs.StringVar(&opts.Host, "a", _EMPTY_, "Network host to listen on.")
  5390  	fs.StringVar(&opts.Host, "net", _EMPTY_, "Network host to listen on.")
  5391  	fs.StringVar(&opts.ClientAdvertise, "client_advertise", _EMPTY_, "Client URL to advertise to other servers.")
  5392  	fs.BoolVar(&opts.Debug, "D", false, "Enable Debug logging.")
  5393  	fs.BoolVar(&opts.Debug, "debug", false, "Enable Debug logging.")
  5394  	fs.BoolVar(&opts.Trace, "V", false, "Enable Trace logging.")
  5395  	fs.BoolVar(&trcAndVerboseTrc, "VV", false, "Enable Verbose Trace logging. (Traces system account as well)")
  5396  	fs.BoolVar(&opts.Trace, "trace", false, "Enable Trace logging.")
  5397  	fs.BoolVar(&dbgAndTrace, "DV", false, "Enable Debug and Trace logging.")
  5398  	fs.BoolVar(&dbgAndTrcAndVerboseTrc, "DVV", false, "Enable Debug and Verbose Trace logging. (Traces system account as well)")
  5399  	fs.BoolVar(&opts.Logtime, "T", true, "Timestamp log entries.")
  5400  	fs.BoolVar(&opts.Logtime, "logtime", true, "Timestamp log entries.")
  5401  	fs.BoolVar(&opts.LogtimeUTC, "logtime_utc", false, "Timestamps in UTC instead of local timezone.")
  5402  	fs.StringVar(&opts.Username, "user", _EMPTY_, "Username required for connection.")
  5403  	fs.StringVar(&opts.Password, "pass", _EMPTY_, "Password required for connection.")
  5404  	fs.StringVar(&opts.Authorization, "auth", _EMPTY_, "Authorization token required for connection.")
  5405  	fs.IntVar(&opts.HTTPPort, "m", 0, "HTTP Port for /varz, /connz endpoints.")
  5406  	fs.IntVar(&opts.HTTPPort, "http_port", 0, "HTTP Port for /varz, /connz endpoints.")
  5407  	fs.IntVar(&opts.HTTPSPort, "ms", 0, "HTTPS Port for /varz, /connz endpoints.")
  5408  	fs.IntVar(&opts.HTTPSPort, "https_port", 0, "HTTPS Port for /varz, /connz endpoints.")
  5409  	fs.StringVar(&configFile, "c", _EMPTY_, "Configuration file.")
  5410  	fs.StringVar(&configFile, "config", _EMPTY_, "Configuration file.")
  5411  	fs.BoolVar(&opts.CheckConfig, "t", false, "Check configuration and exit.")
  5412  	fs.StringVar(&signal, "sl", "", "Send signal to nats-server process (ldm, stop, quit, term, reopen, reload).")
  5413  	fs.StringVar(&signal, "signal", "", "Send signal to nats-server process (ldm, stop, quit, term, reopen, reload).")
  5414  	fs.StringVar(&opts.PidFile, "P", "", "File to store process pid.")
  5415  	fs.StringVar(&opts.PidFile, "pid", "", "File to store process pid.")
  5416  	fs.StringVar(&opts.PortsFileDir, "ports_file_dir", "", "Creates a ports file in the specified directory (<executable_name>_<pid>.ports).")
  5417  	fs.StringVar(&opts.LogFile, "l", "", "File to store logging output.")
  5418  	fs.StringVar(&opts.LogFile, "log", "", "File to store logging output.")
  5419  	fs.Int64Var(&opts.LogSizeLimit, "log_size_limit", 0, "Logfile size limit being auto-rotated")
  5420  	fs.BoolVar(&opts.Syslog, "s", false, "Enable syslog as log method.")
  5421  	fs.BoolVar(&opts.Syslog, "syslog", false, "Enable syslog as log method.")
  5422  	fs.StringVar(&opts.RemoteSyslog, "r", _EMPTY_, "Syslog server addr (udp://127.0.0.1:514).")
  5423  	fs.StringVar(&opts.RemoteSyslog, "remote_syslog", _EMPTY_, "Syslog server addr (udp://127.0.0.1:514).")
  5424  	fs.BoolVar(&showVersion, "version", false, "Print version information.")
  5425  	fs.BoolVar(&showVersion, "v", false, "Print version information.")
  5426  	fs.IntVar(&opts.ProfPort, "profile", 0, "Profiling HTTP port.")
  5427  	fs.StringVar(&opts.RoutesStr, "routes", _EMPTY_, "Routes to actively solicit a connection.")
  5428  	fs.StringVar(&opts.Cluster.ListenStr, "cluster", _EMPTY_, "Cluster url from which members can solicit routes.")
  5429  	fs.StringVar(&opts.Cluster.ListenStr, "cluster_listen", _EMPTY_, "Cluster url from which members can solicit routes.")
  5430  	fs.StringVar(&opts.Cluster.Advertise, "cluster_advertise", _EMPTY_, "Cluster URL to advertise to other servers.")
  5431  	fs.BoolVar(&opts.Cluster.NoAdvertise, "no_advertise", false, "Advertise known cluster IPs to clients.")
  5432  	fs.IntVar(&opts.Cluster.ConnectRetries, "connect_retries", 0, "For implicit routes, number of connect retries.")
  5433  	fs.StringVar(&opts.Cluster.Name, "cluster_name", _EMPTY_, "Cluster Name, if not set one will be dynamically generated.")
  5434  	fs.BoolVar(&showTLSHelp, "help_tls", false, "TLS help.")
  5435  	fs.BoolVar(&opts.TLS, "tls", false, "Enable TLS.")
  5436  	fs.BoolVar(&opts.TLSVerify, "tlsverify", false, "Enable TLS with client verification.")
  5437  	fs.StringVar(&opts.TLSCert, "tlscert", _EMPTY_, "Server certificate file.")
  5438  	fs.StringVar(&opts.TLSKey, "tlskey", _EMPTY_, "Private key for server certificate.")
  5439  	fs.StringVar(&opts.TLSCaCert, "tlscacert", _EMPTY_, "Client certificate CA for verification.")
  5440  	fs.IntVar(&opts.MaxTracedMsgLen, "max_traced_msg_len", 0, "Maximum printable length for traced messages. 0 for unlimited.")
  5441  	fs.BoolVar(&opts.JetStream, "js", false, "Enable JetStream.")
  5442  	fs.BoolVar(&opts.JetStream, "jetstream", false, "Enable JetStream.")
  5443  	fs.StringVar(&opts.StoreDir, "sd", _EMPTY_, "Storage directory.")
  5444  	fs.StringVar(&opts.StoreDir, "store_dir", _EMPTY_, "Storage directory.")
  5445  
  5446  	// The flags definition above set "default" values to some of the options.
  5447  	// Calling Parse() here will override the default options with any value
  5448  	// specified from the command line. This is ok. We will then update the
  5449  	// options with the content of the configuration file (if present), and then,
  5450  	// call Parse() again to override the default+config with command line values.
  5451  	// Calling Parse() before processing config file is necessary since configFile
  5452  	// itself is a command line argument, and also Parse() is required in order
  5453  	// to know if user wants simply to show "help" or "version", etc...
  5454  	if err := fs.Parse(args); err != nil {
  5455  		return nil, err
  5456  	}
  5457  
  5458  	if showVersion {
  5459  		printVersion()
  5460  		return nil, nil
  5461  	}
  5462  
  5463  	if showHelp {
  5464  		printHelp()
  5465  		return nil, nil
  5466  	}
  5467  
  5468  	if showTLSHelp {
  5469  		printTLSHelp()
  5470  		return nil, nil
  5471  	}
  5472  
  5473  	// Process args looking for non-flag options,
  5474  	// 'version' and 'help' only for now
  5475  	showVersion, showHelp, err = ProcessCommandLineArgs(fs)
  5476  	if err != nil {
  5477  		return nil, err
  5478  	} else if showVersion {
  5479  		printVersion()
  5480  		return nil, nil
  5481  	} else if showHelp {
  5482  		printHelp()
  5483  		return nil, nil
  5484  	}
  5485  
  5486  	// Snapshot flag options.
  5487  	FlagSnapshot = opts.Clone()
  5488  
  5489  	// Keep track of the boolean flags that were explicitly set with their value.
  5490  	fs.Visit(func(f *flag.Flag) {
  5491  		switch f.Name {
  5492  		case "DVV":
  5493  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", dbgAndTrcAndVerboseTrc)
  5494  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", dbgAndTrcAndVerboseTrc)
  5495  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "TraceVerbose", dbgAndTrcAndVerboseTrc)
  5496  		case "DV":
  5497  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", dbgAndTrace)
  5498  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", dbgAndTrace)
  5499  		case "D":
  5500  			fallthrough
  5501  		case "debug":
  5502  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", FlagSnapshot.Debug)
  5503  		case "VV":
  5504  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", trcAndVerboseTrc)
  5505  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "TraceVerbose", trcAndVerboseTrc)
  5506  		case "V":
  5507  			fallthrough
  5508  		case "trace":
  5509  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", FlagSnapshot.Trace)
  5510  		case "T":
  5511  			fallthrough
  5512  		case "logtime":
  5513  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Logtime", FlagSnapshot.Logtime)
  5514  		case "s":
  5515  			fallthrough
  5516  		case "syslog":
  5517  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Syslog", FlagSnapshot.Syslog)
  5518  		case "no_advertise":
  5519  			trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Cluster.NoAdvertise", FlagSnapshot.Cluster.NoAdvertise)
  5520  		}
  5521  	})
  5522  
  5523  	// Process signal control.
  5524  	if signal != _EMPTY_ {
  5525  		if err := processSignal(signal); err != nil {
  5526  			return nil, err
  5527  		}
  5528  	}
  5529  
  5530  	// Parse config if given
  5531  	if configFile != _EMPTY_ {
  5532  		// This will update the options with values from the config file.
  5533  		err := opts.ProcessConfigFile(configFile)
  5534  		if err != nil {
  5535  			if opts.CheckConfig {
  5536  				return nil, err
  5537  			}
  5538  			if cerr, ok := err.(*processConfigErr); !ok || len(cerr.Errors()) != 0 {
  5539  				return nil, err
  5540  			}
  5541  			// If we get here we only have warnings and can still continue
  5542  			fmt.Fprint(os.Stderr, err)
  5543  		} else if opts.CheckConfig {
  5544  			// Report configuration file syntax test was successful and exit.
  5545  			return opts, nil
  5546  		}
  5547  
  5548  		// Call this again to override config file options with options from command line.
  5549  		// Note: We don't need to check error here since if there was an error, it would
  5550  		// have been caught the first time this function was called (after setting up the
  5551  		// flags).
  5552  		fs.Parse(args)
  5553  	} else if opts.CheckConfig {
  5554  		return nil, fmt.Errorf("must specify [-c, --config] option to check configuration file syntax")
  5555  	}
  5556  
  5557  	// Special handling of some flags
  5558  	var (
  5559  		flagErr     error
  5560  		tlsDisabled bool
  5561  		tlsOverride bool
  5562  	)
  5563  	fs.Visit(func(f *flag.Flag) {
  5564  		// short-circuit if an error was encountered
  5565  		if flagErr != nil {
  5566  			return
  5567  		}
  5568  		if strings.HasPrefix(f.Name, "tls") {
  5569  			if f.Name == "tls" {
  5570  				if !opts.TLS {
  5571  					// User has specified "-tls=false", we need to disable TLS
  5572  					opts.TLSConfig = nil
  5573  					tlsDisabled = true
  5574  					tlsOverride = false
  5575  					return
  5576  				}
  5577  				tlsOverride = true
  5578  			} else if !tlsDisabled {
  5579  				tlsOverride = true
  5580  			}
  5581  		} else {
  5582  			switch f.Name {
  5583  			case "VV":
  5584  				opts.Trace, opts.TraceVerbose = trcAndVerboseTrc, trcAndVerboseTrc
  5585  			case "DVV":
  5586  				opts.Trace, opts.Debug, opts.TraceVerbose = dbgAndTrcAndVerboseTrc, dbgAndTrcAndVerboseTrc, dbgAndTrcAndVerboseTrc
  5587  			case "DV":
  5588  				// Check value to support -DV=false
  5589  				opts.Trace, opts.Debug = dbgAndTrace, dbgAndTrace
  5590  			case "cluster", "cluster_listen":
  5591  				// Override cluster config if explicitly set via flags.
  5592  				flagErr = overrideCluster(opts)
  5593  			case "routes":
  5594  				// Keep in mind that the flag has updated opts.RoutesStr at this point.
  5595  				if opts.RoutesStr == _EMPTY_ {
  5596  					// Set routes array to nil since routes string is empty
  5597  					opts.Routes = nil
  5598  					return
  5599  				}
  5600  				routeUrls := RoutesFromStr(opts.RoutesStr)
  5601  				opts.Routes = routeUrls
  5602  			}
  5603  		}
  5604  	})
  5605  	if flagErr != nil {
  5606  		return nil, flagErr
  5607  	}
  5608  
  5609  	// This will be true if some of the `-tls` params have been set and
  5610  	// `-tls=false` has not been set.
  5611  	if tlsOverride {
  5612  		if err := overrideTLS(opts); err != nil {
  5613  			return nil, err
  5614  		}
  5615  	}
  5616  
  5617  	// If we don't have cluster defined in the configuration
  5618  	// file and no cluster listen string override, but we do
  5619  	// have a routes override, we need to report misconfiguration.
  5620  	if opts.RoutesStr != _EMPTY_ && opts.Cluster.ListenStr == _EMPTY_ && opts.Cluster.Host == _EMPTY_ && opts.Cluster.Port == 0 {
  5621  		return nil, errors.New("solicited routes require cluster capabilities, e.g. --cluster")
  5622  	}
  5623  
  5624  	return opts, nil
  5625  }
  5626  
  5627  func normalizeBasePath(p string) string {
  5628  	if len(p) == 0 {
  5629  		return "/"
  5630  	}
  5631  	// add leading slash
  5632  	if p[0] != '/' {
  5633  		p = "/" + p
  5634  	}
  5635  	return path.Clean(p)
  5636  }
  5637  
  5638  // overrideTLS is called when at least "-tls=true" has been set.
  5639  func overrideTLS(opts *Options) error {
  5640  	if opts.TLSCert == _EMPTY_ {
  5641  		return errors.New("TLS Server certificate must be present and valid")
  5642  	}
  5643  	if opts.TLSKey == _EMPTY_ {
  5644  		return errors.New("TLS Server private key must be present and valid")
  5645  	}
  5646  
  5647  	tc := TLSConfigOpts{}
  5648  	tc.CertFile = opts.TLSCert
  5649  	tc.KeyFile = opts.TLSKey
  5650  	tc.CaFile = opts.TLSCaCert
  5651  	tc.Verify = opts.TLSVerify
  5652  	tc.Ciphers = defaultCipherSuites()
  5653  
  5654  	var err error
  5655  	opts.TLSConfig, err = GenTLSConfig(&tc)
  5656  	return err
  5657  }
  5658  
  5659  // overrideCluster updates Options.Cluster if that flag "cluster" (or "cluster_listen")
  5660  // has explicitly be set in the command line. If it is set to empty string, it will
  5661  // clear the Cluster options.
  5662  func overrideCluster(opts *Options) error {
  5663  	if opts.Cluster.ListenStr == _EMPTY_ {
  5664  		// This one is enough to disable clustering.
  5665  		opts.Cluster.Port = 0
  5666  		return nil
  5667  	}
  5668  	// -1 will fail url.Parse, so if we have -1, change it to
  5669  	// 0, and then after parse, replace the port with -1 so we get
  5670  	// automatic port allocation
  5671  	wantsRandom := false
  5672  	if strings.HasSuffix(opts.Cluster.ListenStr, ":-1") {
  5673  		wantsRandom = true
  5674  		cls := fmt.Sprintf("%s:0", opts.Cluster.ListenStr[0:len(opts.Cluster.ListenStr)-3])
  5675  		opts.Cluster.ListenStr = cls
  5676  	}
  5677  	clusterURL, err := url.Parse(opts.Cluster.ListenStr)
  5678  	if err != nil {
  5679  		return err
  5680  	}
  5681  	h, p, err := net.SplitHostPort(clusterURL.Host)
  5682  	if err != nil {
  5683  		return err
  5684  	}
  5685  	if wantsRandom {
  5686  		p = "-1"
  5687  	}
  5688  	opts.Cluster.Host = h
  5689  	_, err = fmt.Sscan(p, &opts.Cluster.Port)
  5690  	if err != nil {
  5691  		return err
  5692  	}
  5693  
  5694  	if clusterURL.User != nil {
  5695  		pass, hasPassword := clusterURL.User.Password()
  5696  		if !hasPassword {
  5697  			return errors.New("expected cluster password to be set")
  5698  		}
  5699  		opts.Cluster.Password = pass
  5700  
  5701  		user := clusterURL.User.Username()
  5702  		opts.Cluster.Username = user
  5703  	} else {
  5704  		// Since we override from flag and there is no user/pwd, make
  5705  		// sure we clear what we may have gotten from config file.
  5706  		opts.Cluster.Username = _EMPTY_
  5707  		opts.Cluster.Password = _EMPTY_
  5708  	}
  5709  
  5710  	return nil
  5711  }
  5712  
  5713  func processSignal(signal string) error {
  5714  	var (
  5715  		pid           string
  5716  		commandAndPid = strings.Split(signal, "=")
  5717  	)
  5718  	if l := len(commandAndPid); l == 2 {
  5719  		pid = maybeReadPidFile(commandAndPid[1])
  5720  	} else if l > 2 {
  5721  		return fmt.Errorf("invalid signal parameters: %v", commandAndPid[2:])
  5722  	}
  5723  	if err := ProcessSignal(Command(commandAndPid[0]), pid); err != nil {
  5724  		return err
  5725  	}
  5726  	os.Exit(0)
  5727  	return nil
  5728  }
  5729  
  5730  // maybeReadPidFile returns a PID or Windows service name obtained via the following method:
  5731  // 1. Try to open a file with path "pidStr" (absolute or relative).
  5732  // 2. If such a file exists and can be read, return its contents.
  5733  // 3. Otherwise, return the original "pidStr" string.
  5734  func maybeReadPidFile(pidStr string) string {
  5735  	if b, err := os.ReadFile(pidStr); err == nil {
  5736  		return string(b)
  5737  	}
  5738  	return pidStr
  5739  }
  5740  
  5741  func homeDir() (string, error) {
  5742  	if runtime.GOOS == "windows" {
  5743  		homeDrive, homePath := os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH")
  5744  		userProfile := os.Getenv("USERPROFILE")
  5745  
  5746  		home := filepath.Join(homeDrive, homePath)
  5747  		if homeDrive == _EMPTY_ || homePath == _EMPTY_ {
  5748  			if userProfile == _EMPTY_ {
  5749  				return _EMPTY_, errors.New("nats: failed to get home dir, require %HOMEDRIVE% and %HOMEPATH% or %USERPROFILE%")
  5750  			}
  5751  			home = userProfile
  5752  		}
  5753  
  5754  		return home, nil
  5755  	}
  5756  
  5757  	home := os.Getenv("HOME")
  5758  	if home == _EMPTY_ {
  5759  		return _EMPTY_, errors.New("failed to get home dir, require $HOME")
  5760  	}
  5761  	return home, nil
  5762  }
  5763  
  5764  func expandPath(p string) (string, error) {
  5765  	p = os.ExpandEnv(p)
  5766  
  5767  	if !strings.HasPrefix(p, "~") {
  5768  		return p, nil
  5769  	}
  5770  
  5771  	home, err := homeDir()
  5772  	if err != nil {
  5773  		return _EMPTY_, err
  5774  	}
  5775  
  5776  	return filepath.Join(home, p[1:]), nil
  5777  }