ipn/ipnlocal: q-encode (RFC 2047) Tailscale serve header values

Updates #11603

RELNOTE=Tailscale serve headers are now RFC 2047 Q-encoded

Change-Id: I1314b65ecf5d39a5a601676346ec2c334fdef042
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-04-03 08:48:58 -07:00
committed by Brad Fitzpatrick
parent 262fa8a01e
commit b9611461e5
2 changed files with 37 additions and 2 deletions

View File

@@ -12,6 +12,7 @@ import (
"errors"
"fmt"
"io"
"mime"
"net"
"net/http"
"net/http/httputil"
@@ -25,6 +26,7 @@ import (
"sync"
"sync/atomic"
"time"
"unicode/utf8"
"golang.org/x/net/http2"
"tailscale.com/ipn"
@@ -717,12 +719,27 @@ func (b *LocalBackend) addTailscaleIdentityHeaders(r *httputil.ProxyRequest) {
// Only currently set for nodes with user identities.
return
}
r.Out.Header.Set("Tailscale-User-Login", user.LoginName)
r.Out.Header.Set("Tailscale-User-Name", user.DisplayName)
r.Out.Header.Set("Tailscale-User-Login", encTailscaleHeaderValue(user.LoginName))
r.Out.Header.Set("Tailscale-User-Name", encTailscaleHeaderValue(user.DisplayName))
r.Out.Header.Set("Tailscale-User-Profile-Pic", user.ProfilePicURL)
r.Out.Header.Set("Tailscale-Headers-Info", "https://tailscale.com/s/serve-headers")
}
// encTailscaleHeaderValue cleans or encodes as necessary v, to be suitable in
// an HTTP header value. See
// https://github.com/tailscale/tailscale/issues/11603.
//
// If v is not a valid UTF-8 string, it returns an empty string.
// If v is a valid ASCII string, it returns v unmodified.
// If v is a valid UTF-8 string with non-ASCII characters, it returns a
// RFC 2047 Q-encoded string.
func encTailscaleHeaderValue(v string) string {
if !utf8.ValidString(v) {
return ""
}
return mime.QEncoding.Encode("utf-8", v)
}
// serveWebHandler is an http.HandlerFunc that maps incoming requests to the
// correct *http.
func (b *LocalBackend) serveWebHandler(w http.ResponseWriter, r *http.Request) {