• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats-server / 19188141845

07 Nov 2025 01:16PM UTC coverage: 84.586% (-1.4%) from 86.033%
19188141845

push

github

web-flow
Add meta snapshot metrics to jsz monitoring (#7524)

Exposes snapshot related metrics under /jsz

```js
"meta_cluster": {
    "pending": 0,
    "snapshot": {
        "pending_entries": 1,
        "pending_size": 1314,
        "last_time": "2025-11-06T18:14:40.659678019Z", # UTC
        "last_duration": 161096363
     }
}
```

Signed-off-by: Waldemar Quevedo <wally@nats.io>

73649 of 87070 relevant lines covered (84.59%)

340562.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.13
/server/auth.go
1
// Copyright 2012-2025 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
        "crypto/sha256"
18
        "crypto/subtle"
19
        "crypto/tls"
20
        "crypto/x509/pkix"
21
        "encoding/asn1"
22
        "encoding/base64"
23
        "encoding/hex"
24
        "fmt"
25
        "net"
26
        "net/url"
27
        "regexp"
28
        "slices"
29
        "strings"
30
        "sync/atomic"
31
        "time"
32

33
        "github.com/nats-io/jwt/v2"
34
        "github.com/nats-io/nats-server/v2/internal/ldap"
35
        "github.com/nats-io/nkeys"
36
        "golang.org/x/crypto/bcrypt"
37
)
38

39
// Authentication is an interface for implementing authentication
40
type Authentication interface {
41
        // Check if a client is authorized to connect
42
        Check(c ClientAuthentication) bool
43
}
44

45
// ClientAuthentication is an interface for client authentication
46
type ClientAuthentication interface {
47
        // GetOpts gets options associated with a client
48
        GetOpts() *ClientOpts
49
        // GetTLSConnectionState if TLS is enabled, TLS ConnectionState, nil otherwise
50
        GetTLSConnectionState() *tls.ConnectionState
51
        // RegisterUser optionally map a user after auth.
52
        RegisterUser(*User)
53
        // RemoteAddress expose the connection information of the client
54
        RemoteAddress() net.Addr
55
        // GetNonce is the nonce presented to the user in the INFO line
56
        GetNonce() []byte
57
        // Kind indicates what type of connection this is matching defined constants like CLIENT, ROUTER, GATEWAY, LEAF etc
58
        Kind() int
59
}
60

61
// NkeyUser is for multiple nkey based users
62
type NkeyUser struct {
63
        Nkey                   string              `json:"user"`
64
        Issued                 int64               `json:"issued,omitempty"` // this is a copy of the issued at (iat) field in the jwt
65
        Permissions            *Permissions        `json:"permissions,omitempty"`
66
        Account                *Account            `json:"account,omitempty"`
67
        SigningKey             string              `json:"signing_key,omitempty"`
68
        AllowedConnectionTypes map[string]struct{} `json:"connection_types,omitempty"`
69
        ProxyRequired          bool                `json:"proxy_required,omitempty"`
70
}
71

72
// User is for multiple accounts/users.
73
type User struct {
74
        Username               string              `json:"user"`
75
        Password               string              `json:"password"`
76
        Permissions            *Permissions        `json:"permissions,omitempty"`
77
        Account                *Account            `json:"account,omitempty"`
78
        ConnectionDeadline     time.Time           `json:"connection_deadline,omitempty"`
79
        AllowedConnectionTypes map[string]struct{} `json:"connection_types,omitempty"`
80
        ProxyRequired          bool                `json:"proxy_required,omitempty"`
81
}
82

83
// clone performs a deep copy of the User struct, returning a new clone with
84
// all values copied.
85
func (u *User) clone() *User {
11,914✔
86
        if u == nil {
11,915✔
87
                return nil
1✔
88
        }
1✔
89
        clone := &User{}
11,913✔
90
        *clone = *u
11,913✔
91
        // Account is not cloned because it is always by reference to an existing struct.
11,913✔
92
        clone.Permissions = u.Permissions.clone()
11,913✔
93

11,913✔
94
        if u.AllowedConnectionTypes != nil {
11,928✔
95
                clone.AllowedConnectionTypes = make(map[string]struct{})
15✔
96
                for k, v := range u.AllowedConnectionTypes {
36✔
97
                        clone.AllowedConnectionTypes[k] = v
21✔
98
                }
21✔
99
        }
100

101
        return clone
11,913✔
102
}
103

104
// clone performs a deep copy of the NkeyUser struct, returning a new clone with
105
// all values copied.
106
func (n *NkeyUser) clone() *NkeyUser {
64✔
107
        if n == nil {
64✔
108
                return nil
×
109
        }
×
110
        clone := &NkeyUser{}
64✔
111
        *clone = *n
64✔
112
        // Account is not cloned because it is always by reference to an existing struct.
64✔
113
        clone.Permissions = n.Permissions.clone()
64✔
114

64✔
115
        if n.AllowedConnectionTypes != nil {
65✔
116
                clone.AllowedConnectionTypes = make(map[string]struct{})
1✔
117
                for k, v := range n.AllowedConnectionTypes {
2✔
118
                        clone.AllowedConnectionTypes[k] = v
1✔
119
                }
1✔
120
        }
121

122
        return clone
64✔
123
}
124

125
// SubjectPermission is an individual allow and deny struct for publish
126
// and subscribe authorizations.
127
type SubjectPermission struct {
128
        Allow []string `json:"allow,omitempty"`
129
        Deny  []string `json:"deny,omitempty"`
130
}
131

132
// ResponsePermission can be used to allow responses to any reply subject
133
// that is received on a valid subscription.
134
type ResponsePermission struct {
135
        MaxMsgs int           `json:"max"`
136
        Expires time.Duration `json:"ttl"`
137
}
138

139
// Permissions are the allowed subjects on a per
140
// publish or subscribe basis.
141
type Permissions struct {
142
        Publish   *SubjectPermission  `json:"publish"`
143
        Subscribe *SubjectPermission  `json:"subscribe"`
144
        Response  *ResponsePermission `json:"responses,omitempty"`
145
}
146

147
// RoutePermissions are similar to user permissions
148
// but describe what a server can import/export from and to
149
// another server.
150
type RoutePermissions struct {
151
        Import *SubjectPermission `json:"import"`
152
        Export *SubjectPermission `json:"export"`
153
}
154

155
// clone will clone an individual subject permission.
156
func (p *SubjectPermission) clone() *SubjectPermission {
1,121✔
157
        if p == nil {
1,121✔
158
                return nil
×
159
        }
×
160
        clone := &SubjectPermission{}
1,121✔
161
        if p.Allow != nil {
1,231✔
162
                clone.Allow = make([]string, len(p.Allow))
110✔
163
                copy(clone.Allow, p.Allow)
110✔
164
        }
110✔
165
        if p.Deny != nil {
2,146✔
166
                clone.Deny = make([]string, len(p.Deny))
1,025✔
167
                copy(clone.Deny, p.Deny)
1,025✔
168
        }
1,025✔
169
        return clone
1,121✔
170
}
171

172
// clone performs a deep copy of the Permissions struct, returning a new clone
173
// with all values copied.
174
func (p *Permissions) clone() *Permissions {
12,977✔
175
        if p == nil {
24,875✔
176
                return nil
11,898✔
177
        }
11,898✔
178
        clone := &Permissions{}
1,079✔
179
        if p.Publish != nil {
1,135✔
180
                clone.Publish = p.Publish.clone()
56✔
181
        }
56✔
182
        if p.Subscribe != nil {
2,144✔
183
                clone.Subscribe = p.Subscribe.clone()
1,065✔
184
        }
1,065✔
185
        if p.Response != nil {
1,090✔
186
                clone.Response = &ResponsePermission{
11✔
187
                        MaxMsgs: p.Response.MaxMsgs,
11✔
188
                        Expires: p.Response.Expires,
11✔
189
                }
11✔
190
        }
11✔
191
        return clone
1,079✔
192
}
193

194
// checkAuthforWarnings will look for insecure settings and log concerns.
195
// Lock is assumed held.
196
func (s *Server) checkAuthforWarnings() {
6,715✔
197
        warn := false
6,715✔
198
        opts := s.getOpts()
6,715✔
199
        if opts.Password != _EMPTY_ && !isBcrypt(opts.Password) {
6,742✔
200
                warn = true
27✔
201
        }
27✔
202
        for _, u := range s.users {
10,962✔
203
                // Skip warn if using TLS certs based auth
4,247✔
204
                // unless a password has been left in the config.
4,247✔
205
                if u.Password == _EMPTY_ && opts.TLSMap {
4,287✔
206
                        continue
40✔
207
                }
208
                // Check if this is our internal sys client created on the fly.
209
                if s.sysAccOnlyNoAuthUser != _EMPTY_ && u.Username == s.sysAccOnlyNoAuthUser {
4,643✔
210
                        continue
436✔
211
                }
212
                if !isBcrypt(u.Password) {
7,524✔
213
                        warn = true
3,753✔
214
                        break
3,753✔
215
                }
216
        }
217
        if warn {
10,495✔
218
                // Warning about using plaintext passwords.
3,780✔
219
                s.Warnf("Plaintext passwords detected, use nkeys or bcrypt")
3,780✔
220
        }
3,780✔
221
}
222

223
// If Users or Nkeys options have definitions without an account defined,
224
// assign them to the default global account.
225
// Lock should be held.
226
func (s *Server) assignGlobalAccountToOrphanUsers(nkeys map[string]*NkeyUser, users map[string]*User) {
5,089✔
227
        for _, u := range users {
16,997✔
228
                if u.Account == nil {
12,059✔
229
                        u.Account = s.gacc
151✔
230
                }
151✔
231
        }
232
        for _, u := range nkeys {
5,153✔
233
                if u.Account == nil {
94✔
234
                        u.Account = s.gacc
30✔
235
                }
30✔
236
        }
237
}
238

239
// If the given permissions has a ResponsePermission
240
// set, ensure that defaults are set (if values are 0)
241
// and that a Publish permission is set, and Allow
242
// is disabled if not explicitly set.
243
func validateResponsePermissions(p *Permissions) {
82✔
244
        if p == nil || p.Response == nil {
148✔
245
                return
66✔
246
        }
66✔
247
        if p.Publish == nil {
23✔
248
                p.Publish = &SubjectPermission{}
7✔
249
        }
7✔
250
        if p.Publish.Allow == nil {
23✔
251
                // We turn off the blanket allow statement.
7✔
252
                p.Publish.Allow = []string{}
7✔
253
        }
7✔
254
        // If there is a response permission, ensure
255
        // that if value is 0, we set the default value.
256
        if p.Response.MaxMsgs == 0 {
17✔
257
                p.Response.MaxMsgs = DEFAULT_ALLOW_RESPONSE_MAX_MSGS
1✔
258
        }
1✔
259
        if p.Response.Expires == 0 {
17✔
260
                p.Response.Expires = DEFAULT_ALLOW_RESPONSE_EXPIRATION
1✔
261
        }
1✔
262
}
263

264
// configureAuthorization will do any setup needed for authorization.
265
// Lock is assumed held.
266
func (s *Server) configureAuthorization() {
8,334✔
267
        opts := s.getOpts()
8,334✔
268
        if opts == nil {
8,334✔
269
                return
×
270
        }
×
271

272
        // Check for multiple users first
273
        // This just checks and sets up the user map if we have multiple users.
274
        if opts.CustomClientAuthentication != nil {
8,337✔
275
                s.info.AuthRequired = true
3✔
276
        } else if s.trustedKeys != nil {
8,742✔
277
                s.info.AuthRequired = true
408✔
278
        } else if opts.Nkeys != nil || opts.Users != nil {
13,420✔
279
                s.nkeys, s.users = s.buildNkeysAndUsersFromOptions(opts.Nkeys, opts.Users)
5,089✔
280
                s.info.AuthRequired = true
5,089✔
281
        } else if opts.Username != _EMPTY_ || opts.Authorization != _EMPTY_ {
7,979✔
282
                s.info.AuthRequired = true
56✔
283
        } else {
2,834✔
284
                s.users = nil
2,778✔
285
                s.nkeys = nil
2,778✔
286
                s.info.AuthRequired = false
2,778✔
287
        }
2,778✔
288

289
        // Do similar for websocket config
290
        s.wsConfigAuth(&opts.Websocket)
8,334✔
291
        // And for mqtt config
8,334✔
292
        s.mqttConfigAuth(&opts.MQTT)
8,334✔
293

8,334✔
294
        // Check for server configured auth callouts.
8,334✔
295
        if opts.AuthCallout != nil {
8,355✔
296
                s.mu.Unlock()
21✔
297
                // Give operator log entries if not valid account and auth_users.
21✔
298
                _, err := s.lookupAccount(opts.AuthCallout.Account)
21✔
299
                s.mu.Lock()
21✔
300
                if err != nil {
21✔
301
                        s.Errorf("Authorization callout account %q not valid", opts.AuthCallout.Account)
×
302
                }
×
303
                for _, u := range opts.AuthCallout.AuthUsers {
43✔
304
                        // Check for user in users and nkeys since this is server config.
22✔
305
                        var found bool
22✔
306
                        if len(s.users) > 0 {
44✔
307
                                _, found = s.users[u]
22✔
308
                        }
22✔
309
                        if !found && len(s.nkeys) > 0 {
22✔
310
                                _, found = s.nkeys[u]
×
311
                        }
×
312
                        if !found {
22✔
313
                                s.Errorf("Authorization callout user %q not valid: %v", u, err)
×
314
                        }
×
315
                }
316
        }
317
}
318

319
// Takes the given slices of NkeyUser and User options and build
320
// corresponding maps used by the server. The users are cloned
321
// so that server does not reference options.
322
// The global account is assigned to users that don't have an
323
// existing account.
324
// Server lock is held on entry.
325
func (s *Server) buildNkeysAndUsersFromOptions(nko []*NkeyUser, uo []*User) (map[string]*NkeyUser, map[string]*User) {
5,089✔
326
        var nkeys map[string]*NkeyUser
5,089✔
327
        var users map[string]*User
5,089✔
328

5,089✔
329
        if nko != nil {
5,127✔
330
                nkeys = make(map[string]*NkeyUser, len(nko))
38✔
331
                for _, u := range nko {
102✔
332
                        copy := u.clone()
64✔
333
                        if u.Account != nil {
98✔
334
                                if v, ok := s.accounts.Load(u.Account.Name); ok {
68✔
335
                                        copy.Account = v.(*Account)
34✔
336
                                }
34✔
337
                        }
338
                        if copy.Permissions != nil {
64✔
339
                                validateResponsePermissions(copy.Permissions)
×
340
                        }
×
341
                        nkeys[u.Nkey] = copy
64✔
342
                }
343
        }
344
        if uo != nil {
10,170✔
345
                users = make(map[string]*User, len(uo))
5,081✔
346
                for _, u := range uo {
16,989✔
347
                        copy := u.clone()
11,908✔
348
                        if u.Account != nil {
23,665✔
349
                                if v, ok := s.accounts.Load(u.Account.Name); ok {
23,514✔
350
                                        copy.Account = v.(*Account)
11,757✔
351
                                }
11,757✔
352
                        }
353
                        if copy.Permissions != nil {
11,985✔
354
                                validateResponsePermissions(copy.Permissions)
77✔
355
                        }
77✔
356
                        users[u.Username] = copy
11,908✔
357
                }
358
        }
359
        s.assignGlobalAccountToOrphanUsers(nkeys, users)
5,089✔
360
        return nkeys, users
5,089✔
361
}
362

363
// checkAuthentication will check based on client type and
364
// return boolean indicating if client is authorized.
365
func (s *Server) checkAuthentication(c *client) bool {
42,716✔
366
        switch c.kind {
42,716✔
367
        case CLIENT:
9,490✔
368
                return s.isClientAuthorized(c)
9,490✔
369
        case ROUTER:
30,700✔
370
                return s.isRouterAuthorized(c)
30,700✔
371
        case GATEWAY:
1,802✔
372
                return s.isGatewayAuthorized(c)
1,802✔
373
        case LEAF:
724✔
374
                return s.isLeafNodeAuthorized(c)
724✔
375
        default:
×
376
                return false
×
377
        }
378
}
379

380
// isClientAuthorized will check the client against the proper authorization method and data.
381
// This could be nkey, token, or username/password based.
382
func (s *Server) isClientAuthorized(c *client) bool {
12,947✔
383
        opts := s.getOpts()
12,947✔
384

12,947✔
385
        // Check custom auth first, then jwts, then nkeys, then
12,947✔
386
        // multiple users with TLS map if enabled, then token,
12,947✔
387
        // then single user/pass.
12,947✔
388
        if opts.CustomClientAuthentication != nil && !opts.CustomClientAuthentication.Check(c) {
12,947✔
389
                return false
×
390
        }
×
391

392
        if opts.CustomClientAuthentication == nil && !s.processClientOrLeafAuthentication(c, opts) {
13,133✔
393
                return false
186✔
394
        }
186✔
395

396
        if c.kind == CLIENT || c.kind == LEAF {
25,522✔
397
                // Generate an event if we have a system account.
12,761✔
398
                s.accountConnectEvent(c)
12,761✔
399
        }
12,761✔
400

401
        return true
12,761✔
402
}
403

404
// returns false if the client needs to be disconnected
405
func (c *client) matchesPinnedCert(tlsPinnedCerts PinnedCertSet) bool {
1,228✔
406
        if tlsPinnedCerts == nil {
2,449✔
407
                return true
1,221✔
408
        }
1,221✔
409
        tlsState := c.GetTLSConnectionState()
7✔
410
        if tlsState == nil || len(tlsState.PeerCertificates) == 0 || tlsState.PeerCertificates[0] == nil {
7✔
411
                c.Debugf("Failed pinned cert test as client did not provide a certificate")
×
412
                return false
×
413
        }
×
414
        sha := sha256.Sum256(tlsState.PeerCertificates[0].RawSubjectPublicKeyInfo)
7✔
415
        keyId := hex.EncodeToString(sha[:])
7✔
416
        if _, ok := tlsPinnedCerts[keyId]; !ok {
11✔
417
                c.Debugf("Failed pinned cert test for key id: %s", keyId)
4✔
418
                return false
4✔
419
        }
4✔
420
        return true
3✔
421
}
422

423
var (
424
        mustacheRE = regexp.MustCompile(`{{2}([^}]+)}{2}`)
425
)
426

427
func processUserPermissionsTemplate(lim jwt.UserPermissionLimits, ujwt *jwt.UserClaims, acc *Account) (jwt.UserPermissionLimits, error) {
20✔
428
        nArrayCartesianProduct := func(a ...[]string) [][]string {
27✔
429
                c := 1
7✔
430
                for _, a := range a {
18✔
431
                        c *= len(a)
11✔
432
                }
11✔
433
                if c == 0 {
7✔
434
                        return nil
×
435
                }
×
436
                p := make([][]string, c)
7✔
437
                b := make([]string, c*len(a))
7✔
438
                n := make([]int, len(a))
7✔
439
                s := 0
7✔
440
                for i := range p {
30✔
441
                        e := s + len(a)
23✔
442
                        pi := b[s:e]
23✔
443
                        p[i] = pi
23✔
444
                        s = e
23✔
445
                        for j, n := range n {
66✔
446
                                pi[j] = a[j][n]
43✔
447
                        }
43✔
448
                        for j := len(n) - 1; j >= 0; j-- {
54✔
449
                                n[j]++
31✔
450
                                if n[j] < len(a[j]) {
47✔
451
                                        break
16✔
452
                                }
453
                                n[j] = 0
15✔
454
                        }
455
                }
456
                return p
7✔
457
        }
458
        isTag := func(op string) []string {
46✔
459
                if strings.EqualFold("tag(", op[:4]) && strings.HasSuffix(op, ")") {
48✔
460
                        v := strings.TrimPrefix(op, "tag(")
22✔
461
                        v = strings.TrimSuffix(v, ")")
22✔
462
                        return []string{"tag", v}
22✔
463
                } else if strings.EqualFold("account-tag(", op[:12]) && strings.HasSuffix(op, ")") {
30✔
464
                        v := strings.TrimPrefix(op, "account-tag(")
4✔
465
                        v = strings.TrimSuffix(v, ")")
4✔
466
                        return []string{"account-tag", v}
4✔
467
                }
4✔
468
                return nil
×
469
        }
470
        applyTemplate := func(list jwt.StringList, failOnBadSubject bool) (jwt.StringList, error) {
100✔
471
                found := false
80✔
472
        FOR_FIND:
80✔
473
                for i := 0; i < len(list); i++ {
122✔
474
                        // check if templates are present
42✔
475
                        if mustacheRE.MatchString(list[i]) {
56✔
476
                                found = true
14✔
477
                                break FOR_FIND
14✔
478
                        }
479
                }
480
                if !found {
146✔
481
                        return list, nil
66✔
482
                }
66✔
483
                // process the templates
484
                emittedList := make([]string, 0, len(list))
14✔
485
                for i := 0; i < len(list); i++ {
29✔
486
                        // find all the templates {{}} in this acl
15✔
487
                        tokens := mustacheRE.FindAllString(list[i], -1)
15✔
488
                        srcs := make([]string, len(tokens))
15✔
489
                        values := make([][]string, len(tokens))
15✔
490
                        hasTags := false
15✔
491
                        for tokenNum, tk := range tokens {
40✔
492
                                srcs[tokenNum] = tk
25✔
493
                                op := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(tk, "{{"), "}}"))
25✔
494
                                if strings.EqualFold("name()", op) {
31✔
495
                                        values[tokenNum] = []string{ujwt.Name}
6✔
496
                                } else if strings.EqualFold("subject()", op) {
27✔
497
                                        values[tokenNum] = []string{ujwt.Subject}
2✔
498
                                } else if strings.EqualFold("account-name()", op) {
21✔
499
                                        acc.mu.RLock()
2✔
500
                                        values[tokenNum] = []string{acc.nameTag}
2✔
501
                                        acc.mu.RUnlock()
2✔
502
                                } else if strings.EqualFold("account-subject()", op) {
19✔
503
                                        // this always has an issuer account since this is a scoped signer
2✔
504
                                        values[tokenNum] = []string{ujwt.IssuerAccount}
2✔
505
                                } else if isTag(op) != nil {
28✔
506
                                        hasTags = true
13✔
507
                                        match := isTag(op)
13✔
508
                                        var tags jwt.TagList
13✔
509
                                        if match[0] == "account-tag" {
15✔
510
                                                acc.mu.RLock()
2✔
511
                                                tags = acc.tags
2✔
512
                                                acc.mu.RUnlock()
2✔
513
                                        } else {
13✔
514
                                                tags = ujwt.Tags
11✔
515
                                        }
11✔
516
                                        tagPrefix := fmt.Sprintf("%s:", strings.ToLower(match[1]))
13✔
517
                                        var valueList []string
13✔
518
                                        for _, tag := range tags {
64✔
519
                                                if strings.HasPrefix(tag, tagPrefix) {
70✔
520
                                                        tagValue := strings.TrimPrefix(tag, tagPrefix)
19✔
521
                                                        valueList = append(valueList, tagValue)
19✔
522
                                                }
19✔
523
                                        }
524
                                        if len(valueList) != 0 {
22✔
525
                                                values[tokenNum] = valueList
9✔
526
                                        } else if failOnBadSubject {
15✔
527
                                                return nil, fmt.Errorf("generated invalid subject %q: %q is not defined", list[i], match[1])
2✔
528
                                        } else {
4✔
529
                                                // generate an invalid subject?
2✔
530
                                                values[tokenNum] = []string{" "}
2✔
531
                                        }
2✔
532
                                } else if failOnBadSubject {
×
533
                                        return nil, fmt.Errorf("template operation in %q: %q is not defined", list[i], op)
×
534
                                }
×
535
                        }
536
                        if !hasTags {
19✔
537
                                subj := list[i]
6✔
538
                                for idx, m := range srcs {
18✔
539
                                        subj = strings.Replace(subj, m, values[idx][0], -1)
12✔
540
                                }
12✔
541
                                if IsValidSubject(subj) {
12✔
542
                                        emittedList = append(emittedList, subj)
6✔
543
                                } else if failOnBadSubject {
6✔
544
                                        return nil, fmt.Errorf("generated invalid subject")
×
545
                                }
×
546
                        } else {
7✔
547
                                a := nArrayCartesianProduct(values...)
7✔
548
                                for _, aa := range a {
30✔
549
                                        subj := list[i]
23✔
550
                                        for j := 0; j < len(srcs); j++ {
66✔
551
                                                subj = strings.Replace(subj, srcs[j], aa[j], -1)
43✔
552
                                        }
43✔
553
                                        if IsValidSubject(subj) {
44✔
554
                                                emittedList = append(emittedList, subj)
21✔
555
                                        } else if failOnBadSubject {
23✔
556
                                                return nil, fmt.Errorf("generated invalid subject")
×
557
                                        }
×
558
                                }
559
                        }
560
                }
561
                return emittedList, nil
12✔
562
        }
563

564
        subAllowWasNotEmpty := len(lim.Permissions.Sub.Allow) > 0
20✔
565
        pubAllowWasNotEmpty := len(lim.Permissions.Pub.Allow) > 0
20✔
566

20✔
567
        var err error
20✔
568
        if lim.Permissions.Sub.Allow, err = applyTemplate(lim.Permissions.Sub.Allow, false); err != nil {
20✔
569
                return jwt.UserPermissionLimits{}, err
×
570
        } else if lim.Permissions.Sub.Deny, err = applyTemplate(lim.Permissions.Sub.Deny, true); err != nil {
20✔
571
                return jwt.UserPermissionLimits{}, err
×
572
        } else if lim.Permissions.Pub.Allow, err = applyTemplate(lim.Permissions.Pub.Allow, false); err != nil {
20✔
573
                return jwt.UserPermissionLimits{}, err
×
574
        } else if lim.Permissions.Pub.Deny, err = applyTemplate(lim.Permissions.Pub.Deny, true); err != nil {
22✔
575
                return jwt.UserPermissionLimits{}, err
2✔
576
        }
2✔
577

578
        // if pub/sub allow were not empty, but are empty post template processing, add in a "deny >" to compensate
579
        if subAllowWasNotEmpty && len(lim.Permissions.Sub.Allow) == 0 {
19✔
580
                lim.Permissions.Sub.Deny.Add(">")
1✔
581
        }
1✔
582
        if pubAllowWasNotEmpty && len(lim.Permissions.Pub.Allow) == 0 {
18✔
583
                lim.Permissions.Pub.Deny.Add(">")
×
584
        }
×
585
        return lim, nil
18✔
586
}
587

588
func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) (authorized bool) {
12,946✔
589
        var (
12,946✔
590
                nkey *NkeyUser
12,946✔
591
                juc  *jwt.UserClaims
12,946✔
592
                acc  *Account
12,946✔
593
                user *User
12,946✔
594
                ok   bool
12,946✔
595
                err  error
12,946✔
596
                ao   bool // auth override
12,946✔
597
        )
12,946✔
598

12,946✔
599
        // Little helper that will log the error as a debug statement, set the auth error in
12,946✔
600
        // the connection and return false to indicate authentication failure.
12,946✔
601
        setProxyAuthError := func(err error) bool {
12,964✔
602
                c.Debugf(err.Error())
18✔
603
                c.setAuthError(err)
18✔
604
                return false
18✔
605
        }
18✔
606

607
        // Indicate if this connection came from a trusted proxy. Note that if
608
        // trustedProxy could be false even if the connection is proxied, but it
609
        // means that there was no trusted proxy configured.
610
        trustedProxy, ok := s.proxyCheck(c, opts)
12,946✔
611
        if trustedProxy && !ok {
12,952✔
612
                return setProxyAuthError(ErrAuthProxyNotTrusted)
6✔
613
        }
6✔
614

615
        var proxyRequired bool
12,940✔
616
        // Check if we have auth callouts enabled at the server level or in the bound account.
12,940✔
617
        defer func() {
25,880✔
618
                authErr := c.getAuthError()
12,940✔
619
                if authErr == nil {
25,868✔
620
                        authErr = ErrAuthentication
12,928✔
621
                }
12,928✔
622
                reason := getAuthErrClosedState(authErr).String()
12,940✔
623
                // No-op
12,940✔
624
                if juc == nil && opts.AuthCallout == nil {
23,349✔
625
                        if !authorized {
10,476✔
626
                                s.sendAccountAuthErrorEvent(c, c.acc, reason)
67✔
627
                        }
67✔
628
                        return
10,409✔
629
                }
630
                // We have a juc, check if externally managed, i.e. should be delegated
631
                // to the auth callout service.
632
                if juc != nil && !acc.hasExternalAuth() {
4,972✔
633
                        if !authorized {
2,530✔
634
                                s.sendAccountAuthErrorEvent(c, c.acc, reason)
89✔
635
                        }
89✔
636
                        return
2,441✔
637
                }
638
                // Check config-mode. The global account is a condition since users that
639
                // are not found in the config are implicitly bound to the global account.
640
                // This means those users should be implicitly delegated to auth callout
641
                // if configured. Exclude LEAF connections from this check.
642
                if c.kind != LEAF && juc == nil && opts.AuthCallout != nil && c.acc.Name != globalAccountName {
107✔
643
                        // If no allowed accounts are defined, then all accounts are in scope.
17✔
644
                        // Otherwise see if the account is in the list.
17✔
645
                        delegated := len(opts.AuthCallout.AllowedAccounts) == 0
17✔
646
                        if !delegated {
20✔
647
                                for _, n := range opts.AuthCallout.AllowedAccounts {
6✔
648
                                        if n == c.acc.Name {
3✔
649
                                                delegated = true
×
650
                                                break
×
651
                                        }
652
                                }
653
                        }
654

655
                        // Not delegated, so return with previous authorized result.
656
                        if !delegated {
20✔
657
                                if !authorized {
3✔
658
                                        s.sendAccountAuthErrorEvent(c, c.acc, reason)
×
659
                                }
×
660
                                return
3✔
661
                        }
662
                }
663

664
                // We have auth callout set here.
665
                var skip bool
87✔
666
                // Check if we are on the list of auth_users.
87✔
667
                userID := c.getRawAuthUser()
87✔
668
                if juc != nil {
120✔
669
                        skip = acc.isExternalAuthUser(userID)
33✔
670
                } else {
87✔
671
                        for _, u := range opts.AuthCallout.AuthUsers {
111✔
672
                                if userID == u {
79✔
673
                                        skip = true
22✔
674
                                        break
22✔
675
                                }
676
                        }
677
                }
678

679
                // If we are here we have an auth callout defined and we have failed auth so far
680
                // so we will callout to our auth backend for processing.
681
                if !skip {
143✔
682
                        authorized, reason = s.processClientOrLeafCallout(c, opts, proxyRequired, trustedProxy)
56✔
683
                }
56✔
684
                // Check if we are authorized and in the auth callout account, and if so add in deny publish permissions for the auth subject.
685
                if authorized {
150✔
686
                        var authAccountName string
63✔
687
                        if juc == nil && opts.AuthCallout != nil {
101✔
688
                                authAccountName = opts.AuthCallout.Account
38✔
689
                        } else if juc != nil {
88✔
690
                                authAccountName = acc.Name
25✔
691
                        }
25✔
692
                        c.mu.Lock()
63✔
693
                        if c.acc != nil && c.acc.Name == authAccountName {
99✔
694
                                c.mergeDenyPermissions(pub, []string{AuthCalloutSubject})
36✔
695
                        }
36✔
696
                        c.mu.Unlock()
63✔
697
                } else {
24✔
698
                        // If we are here we failed external authorization.
24✔
699
                        // Send an account scoped event. Server config mode acc will be nil,
24✔
700
                        // so lookup the auth callout assigned account, that is where this will be sent.
24✔
701
                        if acc == nil {
40✔
702
                                acc, _ = s.lookupAccount(opts.AuthCallout.Account)
16✔
703
                        }
16✔
704
                        s.sendAccountAuthErrorEvent(c, acc, reason)
24✔
705
                }
706
        }()
707

708
        s.mu.Lock()
12,940✔
709
        authRequired := s.info.AuthRequired
12,940✔
710
        if !authRequired {
15,982✔
711
                // If no auth required for regular clients, then check if
3,042✔
712
                // we have an override for MQTT or Websocket clients.
3,042✔
713
                switch c.clientType() {
3,042✔
714
                case MQTT:
417✔
715
                        authRequired = s.mqtt.authOverride
417✔
716
                case WS:
×
717
                        authRequired = s.websocket.authOverride
×
718
                }
719
        }
720
        if !authRequired {
15,977✔
721
                // TODO(dlc) - If they send us credentials should we fail?
3,037✔
722
                s.mu.Unlock()
3,037✔
723
                if c.kind == LEAF {
3,244✔
724
                        // Auth is not required, register the leaf node with the selected account.
207✔
725
                        // Otherwise, auth needs to match client auth.
207✔
726
                        return s.registerLeafWithAccount(c, opts.LeafNode.Account)
207✔
727
                }
207✔
728
                return true
2,830✔
729
        }
730
        var (
9,903✔
731
                username      string
9,903✔
732
                password      string
9,903✔
733
                token         string
9,903✔
734
                noAuthUser    string
9,903✔
735
                pinnedAcounts map[string]struct{}
9,903✔
736
        )
9,903✔
737
        tlsMap := opts.TLSMap
9,903✔
738
        if c.kind == CLIENT {
19,324✔
739
                switch c.clientType() {
9,421✔
740
                case MQTT:
133✔
741
                        mo := &opts.MQTT
133✔
742
                        // Always override TLSMap.
133✔
743
                        tlsMap = mo.TLSMap
133✔
744
                        // The rest depends on if there was any auth override in
133✔
745
                        // the mqtt's config.
133✔
746
                        if s.mqtt.authOverride {
144✔
747
                                noAuthUser = mo.NoAuthUser
11✔
748
                                username = mo.Username
11✔
749
                                password = mo.Password
11✔
750
                                token = mo.Token
11✔
751
                                ao = true
11✔
752
                        }
11✔
753
                case WS:
3✔
754
                        wo := &opts.Websocket
3✔
755
                        // Always override TLSMap.
3✔
756
                        tlsMap = wo.TLSMap
3✔
757
                        // The rest depends on if there was any auth override in
3✔
758
                        // the websocket's config.
3✔
759
                        if s.websocket.authOverride {
3✔
760
                                noAuthUser = wo.NoAuthUser
×
761
                                username = wo.Username
×
762
                                password = wo.Password
×
763
                                token = wo.Token
×
764
                                ao = true
×
765
                        }
×
766
                }
767
        } else {
482✔
768
                tlsMap = opts.LeafNode.TLSMap
482✔
769
        }
482✔
770

771
        if !ao {
19,795✔
772
                noAuthUser = opts.NoAuthUser
9,892✔
773
                // If a leaf connects using websocket, and websocket{} block has a no_auth_user
9,892✔
774
                // use that one instead.
9,892✔
775
                if c.kind == LEAF && c.isWebsocket() && opts.Websocket.NoAuthUser != _EMPTY_ {
9,893✔
776
                        noAuthUser = opts.Websocket.NoAuthUser
1✔
777
                }
1✔
778
                username = opts.Username
9,892✔
779
                password = opts.Password
9,892✔
780
                token = opts.Authorization
9,892✔
781
        }
782

783
        // Check if we have trustedKeys defined in the server. If so we require a user jwt.
784
        if s.trustedKeys != nil {
12,384✔
785
                if c.opts.JWT == _EMPTY_ && opts.DefaultSentinel != _EMPTY_ {
2,484✔
786
                        c.opts.JWT = opts.DefaultSentinel
3✔
787
                }
3✔
788
                if c.opts.JWT == _EMPTY_ {
2,488✔
789
                        s.mu.Unlock()
7✔
790
                        c.Debugf("Authentication requires a user JWT")
7✔
791
                        return false
7✔
792
                }
7✔
793
                // So we have a valid user jwt here.
794
                juc, err = jwt.DecodeUserClaims(c.opts.JWT)
2,474✔
795
                if err != nil {
2,474✔
796
                        s.mu.Unlock()
×
797
                        c.Debugf("User JWT not valid: %v", err)
×
798
                        return false
×
799
                }
×
800
                if proxyRequired = juc.ProxyRequired; proxyRequired && !trustedProxy {
2,480✔
801
                        s.mu.Unlock()
6✔
802
                        return setProxyAuthError(ErrAuthProxyRequired)
6✔
803
                }
6✔
804
                vr := jwt.CreateValidationResults()
2,468✔
805
                juc.Validate(vr)
2,468✔
806
                if vr.IsBlocking(true) {
2,469✔
807
                        s.mu.Unlock()
1✔
808
                        c.Debugf("User JWT no longer valid: %+v", vr)
1✔
809
                        return false
1✔
810
                }
1✔
811
                pinnedAcounts = opts.resolverPinnedAccounts
2,467✔
812
        }
813

814
        // Check if we have nkeys or users for client.
815
        hasNkeys := len(s.nkeys) > 0
9,889✔
816
        hasUsers := len(s.users) > 0
9,889✔
817
        if hasNkeys {
9,922✔
818
                if (c.kind == CLIENT || c.kind == LEAF) && noAuthUser != _EMPTY_ &&
33✔
819
                        c.opts.Username == _EMPTY_ && c.opts.Password == _EMPTY_ && c.opts.Token == _EMPTY_ && c.opts.Nkey == _EMPTY_ {
37✔
820
                        if _, exists := s.nkeys[noAuthUser]; exists {
5✔
821
                                c.mu.Lock()
1✔
822
                                c.opts.Nkey = noAuthUser
1✔
823
                                c.mu.Unlock()
1✔
824
                        }
1✔
825
                }
826
                if c.opts.Nkey != _EMPTY_ {
50✔
827
                        nkey, ok = s.nkeys[c.opts.Nkey]
17✔
828
                        if !ok || !c.connectionTypeAllowed(nkey.AllowedConnectionTypes) {
17✔
829
                                s.mu.Unlock()
×
830
                                return false
×
831
                        }
×
832
                }
833
        }
834
        if hasUsers && nkey == nil {
17,234✔
835
                // Check if we are tls verify and are mapping users from the client_certificate.
7,345✔
836
                if tlsMap {
7,380✔
837
                        authorized := checkClientTLSCertSubject(c, func(u string, certDN *ldap.DN, _ bool) (string, bool) {
173✔
838
                                // First do literal lookup using the resulting string representation
138✔
839
                                // of RDNSequence as implemented by the pkix package from Go.
138✔
840
                                if u != _EMPTY_ {
248✔
841
                                        usr, ok := s.users[u]
110✔
842
                                        if !ok || !c.connectionTypeAllowed(usr.AllowedConnectionTypes) {
212✔
843
                                                return _EMPTY_, false
102✔
844
                                        }
102✔
845
                                        user = usr
8✔
846
                                        return usr.Username, true
8✔
847
                                }
848

849
                                if certDN == nil {
28✔
850
                                        return _EMPTY_, false
×
851
                                }
×
852

853
                                // Look through the accounts for a DN that is equal to the one
854
                                // presented by the certificate.
855
                                dns := make(map[*User]*ldap.DN)
28✔
856
                                for _, usr := range s.users {
64✔
857
                                        if !c.connectionTypeAllowed(usr.AllowedConnectionTypes) {
37✔
858
                                                continue
1✔
859
                                        }
860
                                        // TODO: Use this utility to make a full validation pass
861
                                        // on start in case tlsmap feature is being used.
862
                                        inputDN, err := ldap.ParseDN(usr.Username)
35✔
863
                                        if err != nil {
36✔
864
                                                continue
1✔
865
                                        }
866
                                        if inputDN.Equal(certDN) {
50✔
867
                                                user = usr
16✔
868
                                                return usr.Username, true
16✔
869
                                        }
16✔
870

871
                                        // In case it did not match exactly, then collect the DNs
872
                                        // and try to match later in case the DN was reordered.
873
                                        dns[usr] = inputDN
18✔
874
                                }
875

876
                                // Check in case the DN was reordered.
877
                                for usr, inputDN := range dns {
26✔
878
                                        if inputDN.RDNsMatch(certDN) {
19✔
879
                                                user = usr
5✔
880
                                                return usr.Username, true
5✔
881
                                        }
5✔
882
                                }
883
                                return _EMPTY_, false
7✔
884
                        })
885
                        if !authorized {
41✔
886
                                s.mu.Unlock()
6✔
887
                                return false
6✔
888
                        }
6✔
889
                        if c.opts.Username != _EMPTY_ {
29✔
890
                                s.Warnf("User %q found in connect proto, but user required from cert", c.opts.Username)
×
891
                        }
×
892
                        // Already checked that the client didn't send a user in connect
893
                        // but we set it here to be able to identify it in the logs.
894
                        c.opts.Username = user.Username
29✔
895
                } else {
7,310✔
896
                        if (c.kind == CLIENT || c.kind == LEAF) && noAuthUser != _EMPTY_ &&
7,310✔
897
                                c.opts.Username == _EMPTY_ && c.opts.Password == _EMPTY_ && c.opts.Token == _EMPTY_ {
8,770✔
898
                                if u, exists := s.users[noAuthUser]; exists {
2,920✔
899
                                        c.mu.Lock()
1,460✔
900
                                        c.opts.Username = u.Username
1,460✔
901
                                        c.opts.Password = u.Password
1,460✔
902
                                        c.mu.Unlock()
1,460✔
903
                                }
1,460✔
904
                        }
905
                        if c.opts.Username != _EMPTY_ {
14,606✔
906
                                user, ok = s.users[c.opts.Username]
7,296✔
907
                                if !ok || !c.connectionTypeAllowed(user.AllowedConnectionTypes) {
7,327✔
908
                                        s.mu.Unlock()
31✔
909
                                        return false
31✔
910
                                }
31✔
911
                        }
912
                }
913
        }
914
        s.mu.Unlock()
9,852✔
915

9,852✔
916
        // If we have a jwt and a userClaim, make sure we have the Account, etc associated.
9,852✔
917
        // We need to look up the account. This will use an account resolver if one is present.
9,852✔
918
        if juc != nil {
12,319✔
919
                issuer := juc.Issuer
2,467✔
920
                if juc.IssuerAccount != _EMPTY_ {
2,501✔
921
                        issuer = juc.IssuerAccount
34✔
922
                }
34✔
923
                if pinnedAcounts != nil {
2,479✔
924
                        if _, ok := pinnedAcounts[issuer]; !ok {
15✔
925
                                c.Debugf("Account %s not listed as operator pinned account", issuer)
3✔
926
                                atomic.AddUint64(&s.pinnedAccFail, 1)
3✔
927
                                return false
3✔
928
                        }
3✔
929
                }
930
                if acc, err = s.LookupAccount(issuer); acc == nil {
2,486✔
931
                        c.Debugf("Account JWT lookup error: %v", err)
22✔
932
                        return false
22✔
933
                }
22✔
934
                acc.mu.RLock()
2,442✔
935
                aissuer := acc.Issuer
2,442✔
936
                acc.mu.RUnlock()
2,442✔
937
                if !s.isTrustedIssuer(aissuer) {
2,442✔
938
                        c.Debugf("Account JWT not signed by trusted operator")
×
939
                        return false
×
940
                }
×
941
                if scope, ok := acc.hasIssuer(juc.Issuer); !ok {
2,445✔
942
                        c.Debugf("User JWT issuer is not known")
3✔
943
                        return false
3✔
944
                } else if scope != nil {
2,456✔
945
                        if err := scope.ValidateScopedSigner(juc); err != nil {
15✔
946
                                c.Debugf("User JWT is not valid: %v", err)
1✔
947
                                return false
1✔
948
                        } else if uSc, ok := scope.(*jwt.UserScope); !ok {
14✔
949
                                c.Debugf("User JWT is not valid")
×
950
                                return false
×
951
                        } else if juc.UserPermissionLimits, err = processUserPermissionsTemplate(uSc.Template, juc, acc); err != nil {
13✔
952
                                c.Debugf("User JWT generated invalid permissions")
×
953
                                return false
×
954
                        }
×
955
                }
956
                if acc.IsExpired() {
2,442✔
957
                        c.Debugf("Account JWT has expired")
4✔
958
                        return false
4✔
959
                }
4✔
960
                if juc.BearerToken && acc.failBearer() {
2,435✔
961
                        c.Debugf("Account does not allow bearer tokens")
1✔
962
                        return false
1✔
963
                }
1✔
964
                // We check the allowed connection types, but only after processing
965
                // of scoped signer (so that it updates `juc` with what is defined
966
                // in the account.
967
                allowedConnTypes, err := convertAllowedConnectionTypes(juc.AllowedConnectionTypes)
2,433✔
968
                if err != nil {
2,435✔
969
                        // We got an error, which means some connection types were unknown. As long as
2✔
970
                        // a valid one is returned, we proceed with auth. If not, we have to reject.
2✔
971
                        // In other words, suppose that JWT allows "WEBSOCKET" in the array. No error
2✔
972
                        // is returned and allowedConnTypes will contain "WEBSOCKET" only.
2✔
973
                        // Client will be rejected if not a websocket client, or proceed with rest of
2✔
974
                        // auth if it is.
2✔
975
                        // Now suppose JWT allows "WEBSOCKET, MQTT" and say MQTT is not known by this
2✔
976
                        // server. In this case, allowedConnTypes would contain "WEBSOCKET" and we
2✔
977
                        // would get `err` indicating that "MQTT" is an unknown connection type.
2✔
978
                        // If a websocket client connects, it should still be allowed, since after all
2✔
979
                        // the admin wanted to allow websocket and mqtt connection types.
2✔
980
                        // However, say that the JWT only allows "MQTT" (and again suppose this server
2✔
981
                        // does not know about MQTT connection type), then since the allowedConnTypes
2✔
982
                        // map would be empty (no valid types found), and since empty means allow-all,
2✔
983
                        // then we should reject because the intent was to allow connections for this
2✔
984
                        // user only as an MQTT client.
2✔
985
                        c.Debugf("%v", err)
2✔
986
                        if len(allowedConnTypes) == 0 {
3✔
987
                                return false
1✔
988
                        }
1✔
989
                }
990
                if !c.connectionTypeAllowed(allowedConnTypes) {
2,436✔
991
                        c.Debugf("Connection type not allowed")
4✔
992
                        return false
4✔
993
                }
4✔
994
                // skip validation of nonce when presented with a bearer token
995
                // FIXME: if BearerToken is only for WSS, need check for server with that port enabled
996
                if !juc.BearerToken {
4,848✔
997
                        // Verify the signature against the nonce.
2,420✔
998
                        if c.opts.Sig == _EMPTY_ {
2,420✔
999
                                c.Debugf("Signature missing")
×
1000
                                return false
×
1001
                        }
×
1002
                        sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig)
2,420✔
1003
                        if err != nil {
2,420✔
1004
                                // Allow fallback to normal base64.
×
1005
                                sig, err = base64.StdEncoding.DecodeString(c.opts.Sig)
×
1006
                                if err != nil {
×
1007
                                        c.Debugf("Signature not valid base64")
×
1008
                                        return false
×
1009
                                }
×
1010
                        }
1011
                        pub, err := nkeys.FromPublicKey(juc.Subject)
2,420✔
1012
                        if err != nil {
2,420✔
1013
                                c.Debugf("User nkey not valid: %v", err)
×
1014
                                return false
×
1015
                        }
×
1016
                        if err := pub.Verify(c.nonce, sig); err != nil {
2,420✔
1017
                                c.Debugf("Signature not verified")
×
1018
                                return false
×
1019
                        }
×
1020
                }
1021
                if acc.checkUserRevoked(juc.Subject, juc.IssuedAt) {
2,431✔
1022
                        c.Debugf("User authentication revoked")
3✔
1023
                        return false
3✔
1024
                }
3✔
1025
                if !validateSrc(juc, c.host) {
2,427✔
1026
                        c.Errorf("Bad src Ip %s", c.host)
2✔
1027
                        return false
2✔
1028
                }
2✔
1029
                allowNow, validFor := validateTimes(juc)
2,423✔
1030
                if !allowNow {
2,427✔
1031
                        c.Errorf("Outside connect times")
4✔
1032
                        return false
4✔
1033
                }
4✔
1034

1035
                nkey = buildInternalNkeyUser(juc, allowedConnTypes, acc)
2,419✔
1036
                if err := c.RegisterNkeyUser(nkey); err != nil {
2,453✔
1037
                        return false
34✔
1038
                }
34✔
1039

1040
                // Warn about JetStream restrictions
1041
                if c.perms != nil {
4,031✔
1042
                        deniedPub := []string{}
1,646✔
1043
                        deniedSub := []string{}
1,646✔
1044
                        for _, sub := range denyAllJs {
9,876✔
1045
                                if c.perms.pub.deny != nil {
8,370✔
1046
                                        if c.perms.pub.deny.HasInterest(sub) {
245✔
1047
                                                deniedPub = append(deniedPub, sub)
105✔
1048
                                        }
105✔
1049
                                }
1050
                                if c.perms.sub.deny != nil {
13,360✔
1051
                                        if c.perms.sub.deny.HasInterest(sub) {
5,235✔
1052
                                                deniedSub = append(deniedSub, sub)
105✔
1053
                                        }
105✔
1054
                                }
1055
                        }
1056
                        if len(deniedPub) > 0 || len(deniedSub) > 0 {
1,667✔
1057
                                c.Noticef("Connected %s has JetStream denied on pub: %v sub: %v", c.kindString(), deniedPub, deniedSub)
21✔
1058
                        }
21✔
1059
                }
1060

1061
                // Hold onto the user's public key.
1062
                c.mu.Lock()
2,385✔
1063
                c.pubKey = juc.Subject
2,385✔
1064
                c.tags = juc.Tags
2,385✔
1065
                c.nameTag = juc.Name
2,385✔
1066
                c.mu.Unlock()
2,385✔
1067

2,385✔
1068
                // Check if we need to set an auth timer if the user jwt expires.
2,385✔
1069
                c.setExpiration(juc.Claims(), validFor)
2,385✔
1070

2,385✔
1071
                acc.mu.RLock()
2,385✔
1072
                c.Debugf("Authenticated JWT: %s %q (claim-name: %q, claim-tags: %q) "+
2,385✔
1073
                        "signed with %q by Account %q (claim-name: %q, claim-tags: %q) signed with %q has mappings %t accused %p",
2,385✔
1074
                        c.kindString(), juc.Subject, juc.Name, juc.Tags, juc.Issuer, issuer, acc.nameTag, acc.tags, acc.Issuer, acc.hasMappings(), acc)
2,385✔
1075
                acc.mu.RUnlock()
2,385✔
1076
                return true
2,385✔
1077
        }
1078

1079
        if nkey != nil {
7,402✔
1080
                if proxyRequired = nkey.ProxyRequired; proxyRequired && !trustedProxy {
19✔
1081
                        return setProxyAuthError(ErrAuthProxyRequired)
2✔
1082
                }
2✔
1083
                // If we did not match noAuthUser check signature which is required.
1084
                if nkey.Nkey != noAuthUser {
29✔
1085
                        if c.opts.Sig == _EMPTY_ {
15✔
1086
                                c.Debugf("Signature missing")
1✔
1087
                                return false
1✔
1088
                        }
1✔
1089
                        sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig)
13✔
1090
                        if err != nil {
13✔
1091
                                // Allow fallback to normal base64.
×
1092
                                sig, err = base64.StdEncoding.DecodeString(c.opts.Sig)
×
1093
                                if err != nil {
×
1094
                                        c.Debugf("Signature not valid base64")
×
1095
                                        return false
×
1096
                                }
×
1097
                        }
1098
                        pub, err := nkeys.FromPublicKey(c.opts.Nkey)
13✔
1099
                        if err != nil {
13✔
1100
                                c.Debugf("User nkey not valid: %v", err)
×
1101
                                return false
×
1102
                        }
×
1103
                        if err := pub.Verify(c.nonce, sig); err != nil {
14✔
1104
                                c.Debugf("Signature not verified")
1✔
1105
                                return false
1✔
1106
                        }
1✔
1107
                }
1108
                if err := c.RegisterNkeyUser(nkey); err != nil {
13✔
1109
                        return false
×
1110
                }
×
1111
                return true
13✔
1112
        }
1113
        if user != nil {
14,662✔
1114
                if proxyRequired = user.ProxyRequired; proxyRequired && !trustedProxy {
7,297✔
1115
                        return setProxyAuthError(ErrAuthProxyRequired)
3✔
1116
                }
3✔
1117
                ok = comparePasswords(user.Password, c.opts.Password)
7,291✔
1118
                // If we are authorized, register the user which will properly setup any permissions
7,291✔
1119
                // for pub/sub authorizations.
7,291✔
1120
                if ok {
14,574✔
1121
                        c.RegisterUser(user)
7,283✔
1122
                }
7,283✔
1123
                return ok
7,291✔
1124
        }
1125

1126
        // Check for the use of simple auth.
1127
        if c.kind == CLIENT || c.kind == LEAF {
148✔
1128
                if proxyRequired = opts.ProxyRequired; proxyRequired && !trustedProxy {
75✔
1129
                        return setProxyAuthError(ErrAuthProxyRequired)
1✔
1130
                }
1✔
1131
                if token != _EMPTY_ {
97✔
1132
                        return comparePasswords(token, c.opts.Token)
24✔
1133
                } else if username != _EMPTY_ {
107✔
1134
                        if username != c.opts.Username {
43✔
1135
                                return false
9✔
1136
                        }
9✔
1137
                        return comparePasswords(password, c.opts.Password)
25✔
1138
                }
1139
        }
1140
        return false
15✔
1141
}
1142

1143
// If there are configured trusted proxies and this connection comes
1144
// from a proxy whose signature can be verified by one of the known
1145
// trusted key, this function will return `true, true`. If the signature
1146
// cannot be verified by any, it will return `true, false`.
1147
// If the connectio is not proxied, or there are no configured trusted
1148
// proxies, then this function returns `false, false`.
1149
//
1150
// Server lock MUST NOT be held on entry since this function will grab
1151
// the read lock to extract the list of proxy trusted keys. The signature
1152
// verification process will be done outside of the lock.
1153
func (s *Server) proxyCheck(c *client, opts *Options) (bool, bool) {
12,976✔
1154
        // If there is no signature or no configured trusted proxy, return false.
12,976✔
1155
        psig := c.opts.ProxySig
12,976✔
1156
        if psig == _EMPTY_ || opts.Proxies == nil || len(opts.Proxies.Trusted) == 0 {
25,938✔
1157
                return false, false
12,962✔
1158
        }
12,962✔
1159
        // Decode the signature.
1160
        sig, err := base64.RawURLEncoding.DecodeString(psig)
14✔
1161
        if err != nil {
16✔
1162
                c.Debugf("Proxy signature not valid base64")
2✔
1163
                return true, false
2✔
1164
        }
2✔
1165
        // Go through the trusted keys and verify the signature.
1166
        s.mu.RLock()
12✔
1167
        keys := slices.Clone(s.proxiesKeyPairs)
12✔
1168
        s.mu.RUnlock()
12✔
1169
        for _, kp := range keys {
30✔
1170
                // We stop at the first that is valid.
18✔
1171
                if err := kp.Verify(c.nonce, sig); err == nil {
26✔
1172
                        pub, _ := kp.PublicKey()
8✔
1173
                        // Track which proxy public key is used by this connection.
8✔
1174
                        c.mu.Lock()
8✔
1175
                        c.proxyKey = pub
8✔
1176
                        cid := c.cid
8✔
1177
                        c.mu.Unlock()
8✔
1178
                        // Track this proxied connection so that it can be closed
8✔
1179
                        // if the trusted key is removed on configuration reload.
8✔
1180
                        s.mu.Lock()
8✔
1181
                        if s.proxiedConns == nil {
9✔
1182
                                s.proxiedConns = make(map[string]map[uint64]*client)
1✔
1183
                        }
1✔
1184
                        clients := s.proxiedConns[pub]
8✔
1185
                        if clients == nil {
15✔
1186
                                clients = make(map[uint64]*client)
7✔
1187
                        }
7✔
1188
                        clients[cid] = c
8✔
1189
                        s.proxiedConns[pub] = clients
8✔
1190
                        s.mu.Unlock()
8✔
1191
                        return true, true
8✔
1192
                }
1193
        }
1194
        // We could not verify the signature, so indicate failure.
1195
        return true, false
4✔
1196
}
1197

1198
func getTLSAuthDCs(rdns *pkix.RDNSequence) string {
56✔
1199
        dcOID := asn1.ObjectIdentifier{0, 9, 2342, 19200300, 100, 1, 25}
56✔
1200
        dcs := []string{}
56✔
1201
        for _, rdn := range *rdns {
197✔
1202
                if len(rdn) == 0 {
141✔
1203
                        continue
×
1204
                }
1205
                for _, atv := range rdn {
285✔
1206
                        value, ok := atv.Value.(string)
144✔
1207
                        if !ok {
144✔
1208
                                continue
×
1209
                        }
1210
                        if atv.Type.Equal(dcOID) {
159✔
1211
                                dcs = append(dcs, "DC="+value)
15✔
1212
                        }
15✔
1213
                }
1214
        }
1215
        return strings.Join(dcs, ",")
56✔
1216
}
1217

1218
type tlsMapAuthFn func(string, *ldap.DN, bool) (string, bool)
1219

1220
func checkClientTLSCertSubject(c *client, fn tlsMapAuthFn) bool {
91✔
1221
        tlsState := c.GetTLSConnectionState()
91✔
1222
        if tlsState == nil {
91✔
1223
                c.Debugf("User required in cert, no TLS connection state")
×
1224
                return false
×
1225
        }
×
1226
        if len(tlsState.PeerCertificates) == 0 {
91✔
1227
                c.Debugf("User required in cert, no peer certificates found")
×
1228
                return false
×
1229
        }
×
1230
        cert := tlsState.PeerCertificates[0]
91✔
1231
        if len(tlsState.PeerCertificates) > 1 {
91✔
1232
                c.Debugf("Multiple peer certificates found, selecting first")
×
1233
        }
×
1234

1235
        hasSANs := len(cert.DNSNames) > 0
91✔
1236
        hasEmailAddresses := len(cert.EmailAddresses) > 0
91✔
1237
        hasSubject := len(cert.Subject.String()) > 0
91✔
1238
        hasURIs := len(cert.URIs) > 0
91✔
1239
        if !hasEmailAddresses && !hasSubject && !hasURIs {
91✔
1240
                c.Debugf("User required in cert, none found")
×
1241
                return false
×
1242
        }
×
1243

1244
        switch {
91✔
1245
        case hasEmailAddresses:
3✔
1246
                for _, u := range cert.EmailAddresses {
7✔
1247
                        if match, ok := fn(u, nil, false); ok {
6✔
1248
                                c.Debugf("Using email found in cert for auth [%q]", match)
2✔
1249
                                return true
2✔
1250
                        }
2✔
1251
                }
1252
                fallthrough
1✔
1253
        case hasSANs:
89✔
1254
                for _, u := range cert.DNSNames {
330✔
1255
                        if match, ok := fn(u, nil, true); ok {
251✔
1256
                                c.Debugf("Using SAN found in cert for auth [%q]", match)
10✔
1257
                                return true
10✔
1258
                        }
10✔
1259
                }
1260
                fallthrough
79✔
1261
        case hasURIs:
79✔
1262
                for _, u := range cert.URIs {
83✔
1263
                        if match, ok := fn(u.String(), nil, false); ok {
6✔
1264
                                c.Debugf("Using URI found in cert for auth [%q]", match)
2✔
1265
                                return true
2✔
1266
                        }
2✔
1267
                }
1268
        }
1269

1270
        // Use the string representation of the full RDN Sequence including
1271
        // the domain components in case there are any.
1272
        rdn := cert.Subject.ToRDNSequence().String()
77✔
1273

77✔
1274
        // Match using the raw subject to avoid ignoring attributes.
77✔
1275
        // https://github.com/golang/go/issues/12342
77✔
1276
        dn, err := ldap.FromRawCertSubject(cert.RawSubject)
77✔
1277
        if err == nil {
154✔
1278
                if match, ok := fn(_EMPTY_, dn, false); ok {
98✔
1279
                        c.Debugf("Using DistinguishedNameMatch for auth [%q]", match)
21✔
1280
                        return true
21✔
1281
                }
21✔
1282
                c.Debugf("DistinguishedNameMatch could not be used for auth [%q]", rdn)
56✔
1283
        }
1284

1285
        var rdns pkix.RDNSequence
56✔
1286
        if _, err := asn1.Unmarshal(cert.RawSubject, &rdns); err == nil {
112✔
1287
                // If found domain components then include roughly following
56✔
1288
                // the order from https://tools.ietf.org/html/rfc2253
56✔
1289
                //
56✔
1290
                // NOTE: The original sequence from string representation by ToRDNSequence does not follow
56✔
1291
                // the correct ordering, so this addition ofdomainComponents would likely be deprecated in
56✔
1292
                // another release in favor of using the correct ordered as parsed by the go-ldap library.
56✔
1293
                //
56✔
1294
                dcs := getTLSAuthDCs(&rdns)
56✔
1295
                if len(dcs) > 0 {
62✔
1296
                        u := strings.Join([]string{rdn, dcs}, ",")
6✔
1297
                        if match, ok := fn(u, nil, false); ok {
6✔
1298
                                c.Debugf("Using RDNSequence for auth [%q]", match)
×
1299
                                return true
×
1300
                        }
×
1301
                        c.Debugf("RDNSequence could not be used for auth [%q]", u)
6✔
1302
                }
1303
        }
1304

1305
        // If no match, then use the string representation of the RDNSequence
1306
        // from the subject without the domainComponents.
1307
        if match, ok := fn(rdn, nil, false); ok {
62✔
1308
                c.Debugf("Using certificate subject for auth [%q]", match)
6✔
1309
                return true
6✔
1310
        }
6✔
1311

1312
        c.Debugf("User in cert [%q], not found", rdn)
50✔
1313
        return false
50✔
1314
}
1315

1316
func dnsAltNameLabels(dnsAltName string) []string {
147✔
1317
        return strings.Split(strings.ToLower(dnsAltName), ".")
147✔
1318
}
147✔
1319

1320
// Check DNS name according to https://tools.ietf.org/html/rfc6125#section-6.4.1
1321
func dnsAltNameMatches(dnsAltNameLabels []string, urls []*url.URL) bool {
234✔
1322
URLS:
234✔
1323
        for _, url := range urls {
498✔
1324
                if url == nil {
264✔
1325
                        continue URLS
×
1326
                }
1327
                hostLabels := strings.Split(strings.ToLower(url.Hostname()), ".")
264✔
1328
                // Following https://tools.ietf.org/html/rfc6125#section-6.4.3, should not => will not, may => will not
264✔
1329
                // The wildcard * never matches multiple label and only matches the left most label.
264✔
1330
                if len(hostLabels) != len(dnsAltNameLabels) {
483✔
1331
                        continue URLS
219✔
1332
                }
1333
                i := 0
45✔
1334
                // only match wildcard on left most label
45✔
1335
                if dnsAltNameLabels[0] == "*" {
53✔
1336
                        i++
8✔
1337
                }
8✔
1338
                for ; i < len(dnsAltNameLabels); i++ {
103✔
1339
                        if dnsAltNameLabels[i] != hostLabels[i] {
76✔
1340
                                continue URLS
18✔
1341
                        }
1342
                }
1343
                return true
27✔
1344
        }
1345
        return false
207✔
1346
}
1347

1348
// checkRouterAuth checks optional router authorization which can be nil or username/password.
1349
func (s *Server) isRouterAuthorized(c *client) bool {
30,988✔
1350
        // Snapshot server options.
30,988✔
1351
        opts := s.getOpts()
30,988✔
1352

30,988✔
1353
        // Check custom auth first, then TLS map if enabled
30,988✔
1354
        // then single user/pass.
30,988✔
1355
        if opts.CustomRouterAuthentication != nil {
30,988✔
1356
                return opts.CustomRouterAuthentication.Check(c)
×
1357
        }
×
1358

1359
        if opts.Cluster.TLSMap || opts.Cluster.TLSCheckKnownURLs {
31,006✔
1360
                return checkClientTLSCertSubject(c, func(user string, _ *ldap.DN, isDNSAltName bool) (string, bool) {
92✔
1361
                        if user == _EMPTY_ {
88✔
1362
                                return _EMPTY_, false
14✔
1363
                        }
14✔
1364
                        if opts.Cluster.TLSCheckKnownURLs && isDNSAltName {
82✔
1365
                                if dnsAltNameMatches(dnsAltNameLabels(user), opts.Routes) {
26✔
1366
                                        return _EMPTY_, true
4✔
1367
                                }
4✔
1368
                        }
1369
                        if opts.Cluster.TLSMap && opts.Cluster.Username == user {
58✔
1370
                                return _EMPTY_, true
2✔
1371
                        }
2✔
1372
                        return _EMPTY_, false
54✔
1373
                })
1374
        }
1375

1376
        if opts.Cluster.Username == _EMPTY_ {
61,794✔
1377
                return true
30,824✔
1378
        }
30,824✔
1379

1380
        if opts.Cluster.Username != c.opts.Username {
149✔
1381
                return false
3✔
1382
        }
3✔
1383
        if !comparePasswords(opts.Cluster.Password, c.opts.Password) {
143✔
1384
                return false
×
1385
        }
×
1386
        return true
143✔
1387
}
1388

1389
// isGatewayAuthorized checks optional gateway authorization which can be nil or username/password.
1390
func (s *Server) isGatewayAuthorized(c *client) bool {
1,802✔
1391
        // Snapshot server options.
1,802✔
1392
        opts := s.getOpts()
1,802✔
1393

1,802✔
1394
        // Check whether TLS map is enabled, otherwise use single user/pass.
1,802✔
1395
        if opts.Gateway.TLSMap || opts.Gateway.TLSCheckKnownURLs {
1,837✔
1396
                return checkClientTLSCertSubject(c, func(user string, _ *ldap.DN, isDNSAltName bool) (string, bool) {
202✔
1397
                        if user == _EMPTY_ {
200✔
1398
                                return _EMPTY_, false
33✔
1399
                        }
33✔
1400
                        if opts.Gateway.TLSCheckKnownURLs && isDNSAltName {
223✔
1401
                                labels := dnsAltNameLabels(user)
89✔
1402
                                for _, gw := range opts.Gateway.Gateways {
265✔
1403
                                        if gw != nil && dnsAltNameMatches(labels, gw.URLs) {
178✔
1404
                                                return _EMPTY_, true
2✔
1405
                                        }
2✔
1406
                                }
1407
                        }
1408
                        if opts.Gateway.TLSMap && opts.Gateway.Username == user {
134✔
1409
                                return _EMPTY_, true
2✔
1410
                        }
2✔
1411
                        return _EMPTY_, false
130✔
1412
                })
1413
        }
1414

1415
        if opts.Gateway.Username == _EMPTY_ {
3,527✔
1416
                return true
1,760✔
1417
        }
1,760✔
1418

1419
        if opts.Gateway.Username != c.opts.Username {
9✔
1420
                return false
2✔
1421
        }
2✔
1422
        return comparePasswords(opts.Gateway.Password, c.opts.Password)
5✔
1423
}
1424

1425
func (s *Server) registerLeafWithAccount(c *client, account string) bool {
222✔
1426
        var err error
222✔
1427
        acc := s.globalAccount()
222✔
1428
        if account != _EMPTY_ {
231✔
1429
                acc, err = s.lookupAccount(account)
9✔
1430
                if err != nil {
9✔
1431
                        s.Errorf("authentication of user %q failed, unable to lookup account %q: %v",
×
1432
                                c.opts.Username, account, err)
×
1433
                        return false
×
1434
                }
×
1435
        }
1436
        if err = c.registerWithAccount(acc); err != nil {
222✔
1437
                return false
×
1438
        }
×
1439
        return true
222✔
1440
}
1441

1442
// isLeafNodeAuthorized will check for auth for an inbound leaf node connection.
1443
func (s *Server) isLeafNodeAuthorized(c *client) bool {
724✔
1444
        opts := s.getOpts()
724✔
1445

724✔
1446
        setProxyAuthError := func(err error) bool {
736✔
1447
                c.Debugf(err.Error())
12✔
1448
                c.setAuthError(err)
12✔
1449
                return false
12✔
1450
        }
12✔
1451

1452
        isAuthorized := func(username, password, account string, proxyRequired bool) bool {
750✔
1453
                trustedProxy, ok := s.proxyCheck(c, opts)
26✔
1454
                if trustedProxy && !ok {
26✔
1455
                        return setProxyAuthError(ErrAuthProxyNotTrusted)
×
1456
                }
×
1457
                // A given user may not be required, but if the boolean is set at the
1458
                // authorization top-level, then override.
1459
                if !proxyRequired && opts.LeafNode.ProxyRequired {
28✔
1460
                        proxyRequired = true
2✔
1461
                }
2✔
1462
                if proxyRequired && !trustedProxy {
35✔
1463
                        return setProxyAuthError(ErrAuthProxyRequired)
9✔
1464
                }
9✔
1465
                if username != c.opts.Username {
19✔
1466
                        return false
2✔
1467
                }
2✔
1468
                if !comparePasswords(password, c.opts.Password) {
16✔
1469
                        return false
1✔
1470
                }
1✔
1471
                return s.registerLeafWithAccount(c, account)
14✔
1472
        }
1473

1474
        // If leafnodes config has an authorization{} stanza, this takes precedence.
1475
        // The user in CONNECT must match. We will bind to the account associated
1476
        // with that user (from the leafnode's authorization{} config).
1477
        if opts.LeafNode.Username != _EMPTY_ {
738✔
1478
                return isAuthorized(opts.LeafNode.Username, opts.LeafNode.Password, opts.LeafNode.Account,
14✔
1479
                        opts.LeafNode.ProxyRequired)
14✔
1480
        } else if opts.LeafNode.Nkey != _EMPTY_ {
728✔
1481
                trustedProxy, ok := s.proxyCheck(c, opts)
4✔
1482
                if trustedProxy && !ok {
4✔
1483
                        return false
×
1484
                }
×
1485
                if opts.LeafNode.ProxyRequired && !trustedProxy {
7✔
1486
                        return setProxyAuthError(ErrAuthProxyRequired)
3✔
1487
                }
3✔
1488
                if c.opts.Nkey != opts.LeafNode.Nkey {
1✔
1489
                        return false
×
1490
                }
×
1491
                if c.opts.Sig == _EMPTY_ {
1✔
1492
                        c.Debugf("Signature missing")
×
1493
                        return false
×
1494
                }
×
1495
                sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig)
1✔
1496
                if err != nil {
1✔
1497
                        // Allow fallback to normal base64.
×
1498
                        sig, err = base64.StdEncoding.DecodeString(c.opts.Sig)
×
1499
                        if err != nil {
×
1500
                                c.Debugf("Signature not valid base64")
×
1501
                                return false
×
1502
                        }
×
1503
                }
1504
                pub, err := nkeys.FromPublicKey(c.opts.Nkey)
1✔
1505
                if err != nil {
1✔
1506
                        c.Debugf("User nkey not valid: %v", err)
×
1507
                        return false
×
1508
                }
×
1509
                if err := pub.Verify(c.nonce, sig); err != nil {
1✔
1510
                        c.Debugf("Signature not verified")
×
1511
                        return false
×
1512
                }
×
1513
                return s.registerLeafWithAccount(c, opts.LeafNode.Account)
1✔
1514
        } else if len(opts.LeafNode.Users) > 0 {
720✔
1515
                if opts.LeafNode.TLSMap {
17✔
1516
                        var user *User
3✔
1517
                        found := checkClientTLSCertSubject(c, func(u string, _ *ldap.DN, _ bool) (string, bool) {
12✔
1518
                                // This is expected to be a very small array.
9✔
1519
                                for _, usr := range opts.LeafNode.Users {
18✔
1520
                                        if u == usr.Username {
11✔
1521
                                                user = usr
2✔
1522
                                                return u, true
2✔
1523
                                        }
2✔
1524
                                }
1525
                                return _EMPTY_, false
7✔
1526
                        })
1527
                        if !found {
4✔
1528
                                return false
1✔
1529
                        }
1✔
1530
                        if c.opts.Username != _EMPTY_ {
3✔
1531
                                s.Warnf("User %q found in connect proto, but user required from cert", c.opts.Username)
1✔
1532
                        }
1✔
1533
                        c.opts.Username = user.Username
2✔
1534
                        // EMPTY will result in $G
2✔
1535
                        accName := _EMPTY_
2✔
1536
                        if user.Account != nil {
3✔
1537
                                accName = user.Account.GetName()
1✔
1538
                        }
1✔
1539
                        // This will authorize since are using an existing user,
1540
                        // but it will also register with proper account.
1541
                        return isAuthorized(user.Username, user.Password, accName, user.ProxyRequired)
2✔
1542
                }
1543

1544
                // This is expected to be a very small array.
1545
                for _, u := range opts.LeafNode.Users {
30✔
1546
                        if u.Username == c.opts.Username {
29✔
1547
                                var accName string
10✔
1548
                                if u.Account != nil {
13✔
1549
                                        accName = u.Account.Name
3✔
1550
                                }
3✔
1551
                                return isAuthorized(u.Username, u.Password, accName, u.ProxyRequired)
10✔
1552
                        }
1553
                }
1554
                return false
1✔
1555
        }
1556

1557
        // We are here if we accept leafnode connections without any credentials.
1558

1559
        // Still, if the CONNECT has some user info, we will bind to the
1560
        // user's account or to the specified default account (if provided)
1561
        // or to the global account.
1562
        return s.isClientAuthorized(c)
692✔
1563
}
1564

1565
// Support for bcrypt stored passwords and tokens.
1566
var validBcryptPrefix = regexp.MustCompile(`^\$2[abxy]\$\d{2}\$.*`)
1567

1568
// isBcrypt checks whether the given password or token is bcrypted.
1569
func isBcrypt(password string) bool {
11,303✔
1570
        if strings.HasPrefix(password, "$") {
11,342✔
1571
                return validBcryptPrefix.MatchString(password)
39✔
1572
        }
39✔
1573

1574
        return false
11,264✔
1575
}
1576

1577
func comparePasswords(serverPassword, clientPassword string) bool {
7,503✔
1578
        // Check to see if the server password is a bcrypt hash
7,503✔
1579
        if isBcrypt(serverPassword) {
7,522✔
1580
                if err := bcrypt.CompareHashAndPassword([]byte(serverPassword), []byte(clientPassword)); err != nil {
21✔
1581
                        return false
2✔
1582
                }
2✔
1583
        } else {
7,484✔
1584
                // stringToBytes should be constant-time near enough compared to
7,484✔
1585
                // turning a string into []byte normally.
7,484✔
1586
                spass := stringToBytes(serverPassword)
7,484✔
1587
                cpass := stringToBytes(clientPassword)
7,484✔
1588
                if subtle.ConstantTimeCompare(spass, cpass) == 0 {
7,508✔
1589
                        return false
24✔
1590
                }
24✔
1591
        }
1592
        return true
7,477✔
1593
}
1594

1595
func validateAuth(o *Options) error {
8,373✔
1596
        if err := validatePinnedCerts(o.TLSPinnedCerts); err != nil {
8,373✔
1597
                return err
×
1598
        }
×
1599
        for _, u := range o.Users {
17,516✔
1600
                if err := validateAllowedConnectionTypes(u.AllowedConnectionTypes); err != nil {
9,144✔
1601
                        return err
1✔
1602
                }
1✔
1603
        }
1604
        for _, u := range o.Nkeys {
8,439✔
1605
                if err := validateAllowedConnectionTypes(u.AllowedConnectionTypes); err != nil {
68✔
1606
                        return err
1✔
1607
                }
1✔
1608
        }
1609
        return validateNoAuthUser(o, o.NoAuthUser)
8,371✔
1610
}
1611

1612
func validateAllowedConnectionTypes(m map[string]struct{}) error {
9,210✔
1613
        for ct := range m {
9,236✔
1614
                ctuc := strings.ToUpper(ct)
26✔
1615
                switch ctuc {
26✔
1616
                case jwt.ConnectionTypeStandard, jwt.ConnectionTypeWebsocket,
1617
                        jwt.ConnectionTypeLeafnode, jwt.ConnectionTypeLeafnodeWS,
1618
                        jwt.ConnectionTypeMqtt, jwt.ConnectionTypeMqttWS,
1619
                        jwt.ConnectionTypeInProcess:
24✔
1620
                default:
2✔
1621
                        return fmt.Errorf("unknown connection type %q", ct)
2✔
1622
                }
1623
                if ctuc != ct {
26✔
1624
                        delete(m, ct)
2✔
1625
                        m[ctuc] = struct{}{}
2✔
1626
                }
2✔
1627
        }
1628
        return nil
9,208✔
1629
}
1630

1631
func validateNoAuthUser(o *Options, noAuthUser string) error {
8,378✔
1632
        if noAuthUser == _EMPTY_ {
16,407✔
1633
                return nil
8,029✔
1634
        }
8,029✔
1635
        if len(o.TrustedOperators) > 0 {
349✔
1636
                return fmt.Errorf("no_auth_user not compatible with Trusted Operator")
×
1637
        }
×
1638

1639
        if o.Nkeys == nil && o.Users == nil {
349✔
1640
                return fmt.Errorf(`no_auth_user: "%s" present, but users/nkeys are not defined`, noAuthUser)
×
1641
        }
×
1642
        for _, u := range o.Users {
856✔
1643
                if u.Username == noAuthUser {
850✔
1644
                        return nil
343✔
1645
                }
343✔
1646
        }
1647
        for _, u := range o.Nkeys {
9✔
1648
                if u.Nkey == noAuthUser {
4✔
1649
                        return nil
1✔
1650
                }
1✔
1651
        }
1652
        return fmt.Errorf(
5✔
1653
                `no_auth_user: "%s" not present as user or nkey in authorization block or account configuration`,
5✔
1654
                noAuthUser)
5✔
1655
}
1656

1657
func validateProxies(o *Options) error {
8,368✔
1658
        if o.Proxies == nil {
16,732✔
1659
                return nil
8,364✔
1660
        }
8,364✔
1661
        for _, p := range o.Proxies.Trusted {
12✔
1662
                if !nkeys.IsValidPublicKey(p.Key) {
9✔
1663
                        return fmt.Errorf("proxy trusted key %q is invalid", p.Key)
1✔
1664
                }
1✔
1665
        }
1666
        return nil
3✔
1667
}
1668

1669
// Create a list of nkeys.KeyPair corresponding to the public keys
1670
// of the Proxies.TrustedKeys list.
1671
// Server lock must be held on entry.
1672
func (s *Server) processProxiesTrustedKeys() {
6,929✔
1673
        // We could be here on reload.
6,929✔
1674
        if s.proxiesKeyPairs != nil {
6,930✔
1675
                s.proxiesKeyPairs = s.proxiesKeyPairs[:0]
1✔
1676
        }
1✔
1677
        if opts := s.getOpts(); opts.Proxies == nil {
13,855✔
1678
                return
6,926✔
1679
        }
6,926✔
1680
        for _, p := range s.getOpts().Proxies.Trusted {
9✔
1681
                // Can't fail since we have already checked that it was a valid key.
6✔
1682
                kp, _ := nkeys.FromPublicKey(p.Key)
6✔
1683
                s.proxiesKeyPairs = append(s.proxiesKeyPairs, kp)
6✔
1684
        }
6✔
1685
}
1686

1687
// Returns the connection's `ClosedState` for the given authenication error.
1688
func getAuthErrClosedState(authErr error) ClosedState {
13,194✔
1689
        switch authErr {
13,194✔
1690
        case ErrAuthProxyNotTrusted:
8✔
1691
                return ProxyNotTrusted
8✔
1692
        case ErrAuthProxyRequired:
41✔
1693
                return ProxyRequired
41✔
1694
        default:
13,145✔
1695
                return AuthenticationViolation
13,145✔
1696
        }
1697
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc