mirror of
https://github.com/fatedier/frp.git
synced 2026-03-08 10:59:11 +08:00
fix: WebsocketListener nil panic and OIDC auth data race (#5204)
- pkg/util/net/websocket.go: store ln parameter in struct to prevent nil pointer panic when Addr() is called - pkg/auth/oidc.go: replace unsynchronized []string with map + RWMutex for subjectsFromLogin to fix data race across concurrent connections
This commit is contained in:
@@ -23,6 +23,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -205,7 +206,8 @@ type OidcAuthConsumer struct {
|
|||||||
additionalAuthScopes []v1.AuthScope
|
additionalAuthScopes []v1.AuthScope
|
||||||
|
|
||||||
verifier TokenVerifier
|
verifier TokenVerifier
|
||||||
subjectsFromLogin []string
|
mu sync.RWMutex
|
||||||
|
subjectsFromLogin map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTokenVerifier(cfg v1.AuthOIDCServerConfig) TokenVerifier {
|
func NewTokenVerifier(cfg v1.AuthOIDCServerConfig) TokenVerifier {
|
||||||
@@ -226,7 +228,7 @@ func NewOidcAuthVerifier(additionalAuthScopes []v1.AuthScope, verifier TokenVeri
|
|||||||
return &OidcAuthConsumer{
|
return &OidcAuthConsumer{
|
||||||
additionalAuthScopes: additionalAuthScopes,
|
additionalAuthScopes: additionalAuthScopes,
|
||||||
verifier: verifier,
|
verifier: verifier,
|
||||||
subjectsFromLogin: []string{},
|
subjectsFromLogin: make(map[string]struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,9 +237,9 @@ func (auth *OidcAuthConsumer) VerifyLogin(loginMsg *msg.Login) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid OIDC token in login: %v", err)
|
return fmt.Errorf("invalid OIDC token in login: %v", err)
|
||||||
}
|
}
|
||||||
if !slices.Contains(auth.subjectsFromLogin, token.Subject) {
|
auth.mu.Lock()
|
||||||
auth.subjectsFromLogin = append(auth.subjectsFromLogin, token.Subject)
|
auth.subjectsFromLogin[token.Subject] = struct{}{}
|
||||||
}
|
auth.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,11 +248,13 @@ func (auth *OidcAuthConsumer) verifyPostLoginToken(privilegeKey string) (err err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid OIDC token in ping: %v", err)
|
return fmt.Errorf("invalid OIDC token in ping: %v", err)
|
||||||
}
|
}
|
||||||
if !slices.Contains(auth.subjectsFromLogin, token.Subject) {
|
auth.mu.RLock()
|
||||||
|
_, ok := auth.subjectsFromLogin[token.Subject]
|
||||||
|
auth.mu.RUnlock()
|
||||||
|
if !ok {
|
||||||
return fmt.Errorf("received different OIDC subject in login and ping. "+
|
return fmt.Errorf("received different OIDC subject in login and ping. "+
|
||||||
"original subjects: %s, "+
|
|
||||||
"new subject: %s",
|
"new subject: %s",
|
||||||
auth.subjectsFromLogin, token.Subject)
|
token.Subject)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type WebsocketListener struct {
|
|||||||
// ln: tcp listener for websocket connections
|
// ln: tcp listener for websocket connections
|
||||||
func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
|
func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
|
||||||
wl = &WebsocketListener{
|
wl = &WebsocketListener{
|
||||||
|
ln: ln,
|
||||||
acceptCh: make(chan net.Conn),
|
acceptCh: make(chan net.Conn),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user