Skip to content

Commit 3981de7

Browse files
committed
hidden domain option for tlscookie:// auth provider
1 parent 3b9c000 commit 3981de7

2 files changed

Lines changed: 62 additions & 18 deletions

File tree

auth/basic.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"net/http"
99
"net/url"
10-
"strconv"
1110
"strings"
1211
"sync"
1312
"sync/atomic"
@@ -157,13 +156,11 @@ func (auth *BasicAuth) Validate(ctx context.Context, wr http.ResponseWriter, req
157156

158157
if pwFile.Match(login, password) {
159158
if auth.hiddenDomain != "" &&
160-
(req.Host == auth.hiddenDomain || req.URL.Host == auth.hiddenDomain) {
161-
wr.Header().Set("Content-Length", strconv.Itoa(len([]byte(AUTH_TRIGGERED_MSG))))
159+
(matchHiddenDomain(req.Host, auth.hiddenDomain) || matchHiddenDomain(req.URL.Host, auth.hiddenDomain)) {
162160
wr.Header().Set("Pragma", "no-cache")
163161
wr.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
164162
wr.Header().Set("Expires", EPOCH_EXPIRE)
165-
wr.Header()["Date"] = nil
166-
wr.WriteHeader(http.StatusOK)
163+
wr.WriteHeader(http.StatusBadRequest)
167164
wr.Write([]byte(AUTH_TRIGGERED_MSG))
168165
return "", false
169166
} else {

auth/tlscookie.go

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ package auth
33
import (
44
"context"
55
"encoding/hex"
6-
"errors"
76
"fmt"
87
"net/http"
98
"net/url"
9+
"strings"
1010
"sync"
1111

1212
"github.com/hashicorp/go-multierror"
@@ -17,14 +17,18 @@ import (
1717

1818
type sessionValidator interface {
1919
Valid(sessionID, _, userAddr string) bool
20+
Close() error
2021
}
2122

2223
type TLSCookieAuth struct {
23-
logger *clog.CondLogger
24-
stopOnce sync.Once
25-
next Auth
26-
reject Auth
27-
lookup sessionValidator
24+
logger *clog.CondLogger
25+
stopOnce sync.Once
26+
next Auth
27+
reject Auth
28+
lookup sessionValidator
29+
hiddenDomain string
30+
lsMux sync.RWMutex
31+
learnedSessions map[tlsutil.TLSSessionID]struct{}
2832
}
2933

3034
func NewTLSCookieAuth(param_url *url.URL, logger *clog.CondLogger) (*TLSCookieAuth, error) {
@@ -33,48 +37,86 @@ func NewTLSCookieAuth(param_url *url.URL, logger *clog.CondLogger) (*TLSCookieAu
3337
return nil, err
3438
}
3539
auth := &TLSCookieAuth{
36-
logger: logger,
40+
logger: logger,
41+
hiddenDomain: strings.ToLower(values.Get("hidden_domain")),
42+
learnedSessions: make(map[tlsutil.TLSSessionID]struct{}),
3743
}
38-
if lookupURL := values.Get("lookup"); lookupURL == "" {
39-
return nil, errors.New("\"lookup\" parameter is mandatory for TLS cookie auth provider")
40-
} else {
44+
if lookupURL := values.Get("lookup"); lookupURL != "" {
4145
lookupAuth, err := NewAuth(lookupURL, logger)
4246
if err != nil {
4347
return nil, fmt.Errorf("unable to construct lookup provider for TLS cookie auth provider: %w", err)
4448
}
4549
lookup, ok := lookupAuth.(sessionValidator)
4650
if !ok {
51+
lookupAuth.Close()
52+
defer auth.Close()
4753
return nil, fmt.Errorf("unable to construct TLS cookie auth provider: provided lookup provider %q is not suitable for session validation", lookupURL)
4854
}
4955
auth.lookup = lookup
5056
}
5157
if nextAuth := values.Get("next"); nextAuth != "" {
5258
nap, err := NewAuth(nextAuth, logger)
5359
if err != nil {
60+
defer auth.Close()
5461
return nil, fmt.Errorf("chained auth provider construction failed: %w", err)
5562
}
5663
auth.next = nap
5764
}
5865
if nextAuth := values.Get("else"); nextAuth != "" {
5966
nap, err := NewAuth(nextAuth, logger)
6067
if err != nil {
68+
defer auth.Close()
6169
return nil, fmt.Errorf("chained auth provider construction failed: %w", err)
6270
}
6371
auth.reject = nap
6472
}
6573
return auth, nil
6674
}
6775

76+
func (auth *TLSCookieAuth) checkLearned(sessionID tlsutil.TLSSessionID) bool {
77+
auth.lsMux.RLock()
78+
defer auth.lsMux.RUnlock()
79+
_, ok := auth.learnedSessions[sessionID]
80+
return ok
81+
}
82+
83+
func (auth *TLSCookieAuth) addLearned(sessionID tlsutil.TLSSessionID) {
84+
auth.lsMux.Lock()
85+
defer auth.lsMux.Unlock()
86+
auth.learnedSessions[sessionID] = struct{}{}
87+
}
88+
6889
func (auth *TLSCookieAuth) Validate(ctx context.Context, wr http.ResponseWriter, req *http.Request) (string, bool) {
6990
sessionID, ok := tlsutil.TLSSessionIDFromContext(ctx)
7091
if !ok {
7192
auth.logger.Debug("tlscookie: no session extracted for %s", req.RemoteAddr)
7293
return auth.handleReject(ctx, wr, req)
7394
}
74-
if !auth.lookup.Valid(hex.EncodeToString(sessionID[:]), "", req.RemoteAddr) {
75-
auth.logger.Info("tlscookie: session ID %x from %s is not permitted", sessionID, req.RemoteAddr)
76-
return auth.handleReject(ctx, wr, req)
95+
if auth.hiddenDomain != "" {
96+
if matchHiddenDomain(req.Host, auth.hiddenDomain) || matchHiddenDomain(req.URL.Host, auth.hiddenDomain) {
97+
auth.logger.Debug("tlscookie: session %x from %s requested magic domain", sessionID, req.RemoteAddr)
98+
auth.addLearned(sessionID)
99+
wr.Header().Set("Pragma", "no-cache")
100+
wr.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
101+
wr.Header().Set("Expires", EPOCH_EXPIRE)
102+
wr.WriteHeader(http.StatusBadRequest)
103+
wr.Write([]byte(AUTH_TRIGGERED_MSG))
104+
return "", false
105+
}
106+
if auth.checkLearned(sessionID) {
107+
auth.logger.Debug("tlscookie: session %x from %s passed because it is in learned set", sessionID, req.RemoteAddr)
108+
return auth.handleSuccess(ctx, wr, req, sessionID)
109+
}
77110
}
111+
if auth.lookup != nil && auth.lookup.Valid(hex.EncodeToString(sessionID[:]), "", req.RemoteAddr) {
112+
auth.logger.Debug("tlscookie: session %x from %s passed because external lookup said yay", sessionID, req.RemoteAddr)
113+
return auth.handleSuccess(ctx, wr, req, sessionID)
114+
}
115+
auth.logger.Info("tlscookie: session ID %x from %s is not permitted", sessionID, req.RemoteAddr)
116+
return auth.handleReject(ctx, wr, req)
117+
}
118+
119+
func (auth *TLSCookieAuth) handleSuccess(ctx context.Context, wr http.ResponseWriter, req *http.Request, sessionID tlsutil.TLSSessionID) (string, bool) {
78120
if auth.next != nil {
79121
return auth.next.Validate(ctx, wr, req)
80122
}
@@ -92,6 +134,11 @@ func (auth *TLSCookieAuth) handleReject(ctx context.Context, wr http.ResponseWri
92134
func (auth *TLSCookieAuth) Close() error {
93135
var err error
94136
auth.stopOnce.Do(func() {
137+
if auth.lookup != nil {
138+
if closeErr := auth.lookup.Close(); closeErr != nil {
139+
err = multierror.Append(err, closeErr)
140+
}
141+
}
95142
if auth.next != nil {
96143
if closeErr := auth.next.Close(); closeErr != nil {
97144
err = multierror.Append(err, closeErr)

0 commit comments

Comments
 (0)