net/tshttpproxy: add start of Kerberos Negotiate auth to proxies on Windows

For now only used by a new cmd/tailscale debug --get-url
subcommand. Not yet wired up to the places making HTTP requests.

Updates tailscale/corp#583
This commit is contained in:
Brad Fitzpatrick
2020-08-25 13:45:15 -07:00
parent dd2c61a519
commit f915ab6552
5 changed files with 89 additions and 1 deletions

View File

@ -5,6 +5,8 @@
package tshttpproxy
import (
"encoding/base64"
"fmt"
"log"
"net/http"
"net/url"
@ -12,6 +14,7 @@ import (
"syscall"
"unsafe"
"github.com/alexbrainman/sspi/negotiate"
"golang.org/x/sys/windows"
)
@ -24,6 +27,7 @@ var (
func init() {
sysProxyFromEnv = proxyFromWinHTTP
sysAuthHeader = sysAuthHeaderWindows
}
func proxyFromWinHTTP(req *http.Request) (*url.URL, error) {
@ -144,3 +148,20 @@ func (hi winHTTPInternet) GetProxyForURL(urlStr string) (string, error) {
}
return "", err
}
func sysAuthHeaderWindows(u *url.URL) (string, error) {
spn := "HTTP/" + u.Hostname()
creds, err := negotiate.AcquireCurrentUserCredentials()
if err != nil {
return "", fmt.Errorf("negotiate.AcquireCurrentUserCredentials: %w", err)
}
defer creds.Release()
secCtx, token, err := negotiate.NewClientContext(creds, spn)
if err != nil {
return "", fmt.Errorf("negotiate.NewClientContext: %w", err)
}
defer secCtx.Release()
return "Negotiate " + base64.StdEncoding.EncodeToString(token), nil
}