From a0732f42d0fec568d696c1cd2b5012b72c1186cf Mon Sep 17 00:00:00 2001 From: snowie2000 Date: Fri, 21 Feb 2025 15:19:07 +0800 Subject: [PATCH] local auth works with tls disabled. verify if the auth method is supported before adding it to the response. --- cmd/rdpgw/config/configuration.go | 6 +----- cmd/rdpgw/main.go | 15 ++++++++------- cmd/rdpgw/web/mux.go | 21 ++++++++++++++++----- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/cmd/rdpgw/config/configuration.go b/cmd/rdpgw/config/configuration.go index ead4140..b1937dd 100644 --- a/cmd/rdpgw/config/configuration.go +++ b/cmd/rdpgw/config/configuration.go @@ -221,13 +221,9 @@ func Load(configFile string) Configuration { log.Fatalf("host selection is set to `signed` but `querytokensigningkey` is not set") } - if Conf.Server.BasicAuthEnabled() && Conf.Server.Tls == "disable" { - log.Fatalf("basicauth=local and tls=disable are mutually exclusive") - } - if Conf.Server.NtlmEnabled() && Conf.Server.KerberosEnabled() { log.Fatalf("ntlm and kerberos authentication are not stackable") - } + } if !Conf.Caps.TokenAuth && Conf.Server.OpenIDEnabled() { log.Fatalf("openid is configured but tokenauth disabled") diff --git a/cmd/rdpgw/main.go b/cmd/rdpgw/main.go index 528106a..eccf9bd 100644 --- a/cmd/rdpgw/main.go +++ b/cmd/rdpgw/main.go @@ -110,7 +110,7 @@ func main() { RdpOpts: web.RdpOpts{ UsernameTemplate: conf.Client.UsernameTemplate, SplitUserDomain: conf.Client.SplitUserDomain, - NoUsername: conf.Client.NoUsername, + NoUsername: conf.Client.NoUsername, }, GatewayAddress: url, TemplateFile: conf.Client.Defaults, @@ -229,23 +229,24 @@ func main() { // for stacking of authentication auth := web.NewAuthMux() rdp.MatcherFunc(web.NoAuthz).HandlerFunc(auth.SetAuthenticate) - + // ntlm if conf.Server.NtlmEnabled() { log.Printf("enabling NTLM authentication") ntlm := web.NTLMAuthHandler{SocketAddress: conf.Server.AuthSocket, Timeout: conf.Server.BasicAuthTimeout} rdp.NewRoute().HeadersRegexp("Authorization", "NTLM").HandlerFunc(ntlm.NTLMAuth(gw.HandleGatewayProtocol)) rdp.NewRoute().HeadersRegexp("Authorization", "Negotiate").HandlerFunc(ntlm.NTLMAuth(gw.HandleGatewayProtocol)) - auth.Register(`NTLM`) - auth.Register(`Negotiate`) - } + auth.Register([]string{`NTLM`, `Negotiate`}, func(r *http.Request) bool { + return r.Header.Get("Sec-WebSocket-Protocol") != "binary" // rdp client for ios is incompatible with this NTLM method. + }) + } // basic auth if conf.Server.BasicAuthEnabled() { log.Printf("enabling basic authentication") q := web.BasicAuthHandler{SocketAddress: conf.Server.AuthSocket, Timeout: conf.Server.BasicAuthTimeout} rdp.NewRoute().HeadersRegexp("Authorization", "Basic").HandlerFunc(q.BasicAuth(gw.HandleGatewayProtocol)) - auth.Register(`Basic realm="restricted", charset="UTF-8"`) + auth.Register([]string{`Basic realm="restricted", charset="UTF-8"`}, nil) } // spnego / kerberos @@ -263,7 +264,7 @@ func main() { // kdcproxy k := kdcproxy.InitKdcProxy(conf.Kerberos.Krb5Conf) r.HandleFunc(kdcProxyEndPoint, k.Handler).Methods("POST") - auth.Register("Negotiate") + auth.Register([]string{"Negotiate"}, nil) } // setup server diff --git a/cmd/rdpgw/web/mux.go b/cmd/rdpgw/web/mux.go index 02069ae..7220e49 100644 --- a/cmd/rdpgw/web/mux.go +++ b/cmd/rdpgw/web/mux.go @@ -5,21 +5,32 @@ import ( "net/http" ) -type AuthMux struct { - headers []string +type authInfo struct { + headers []string + verifier AuthAvailableVerifier } +type AuthMux struct { + headers []authInfo +} + +type AuthAvailableVerifier func(r *http.Request) bool + func NewAuthMux() *AuthMux { return &AuthMux{} } -func (a *AuthMux) Register(s string) { - a.headers = append(a.headers, s) +func (a *AuthMux) Register(s []string, verifier AuthAvailableVerifier) { + a.headers = append(a.headers, authInfo{s, verifier}) } func (a *AuthMux) SetAuthenticate(w http.ResponseWriter, r *http.Request) { for _, s := range a.headers { - w.Header().Add("WWW-Authenticate", s) + if s.verifier == nil || s.verifier(r) { // verify if the auth method works for the target client + for _, h := range s.headers { + w.Header().Add("WWW-Authenticate", h) + } + } } http.Error(w, "Unauthorized", http.StatusUnauthorized) }