http_authenticator.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package upstreamproxy
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strings"
  6. )
  7. type HttpAuthState int
  8. const (
  9. HTTP_AUTH_STATE_UNCHALLENGED HttpAuthState = iota
  10. HTTP_AUTH_STATE_CHALLENGED
  11. HTTP_AUTH_STATE_FAILURE
  12. HTTP_AUTH_STATE_SUCCESS
  13. )
  14. type HttpAuthenticator interface {
  15. authenticate(req *http.Request, username, pasword string) error
  16. }
  17. func newHttpAuthenticator(resp *http.Response) (HttpAuthenticator, error) {
  18. challenges := make(map[string]string)
  19. headers := resp.Header[http.CanonicalHeaderKey("proxy-authenticate")]
  20. for _, val := range headers {
  21. s := strings.SplitN(val, " ", 2)
  22. if len(s) == 2 {
  23. challenges[s[0]] = s[1]
  24. }
  25. if len(s) == 1 && s[0] != "" {
  26. challenges[s[0]] = ""
  27. }
  28. }
  29. if len(challenges) == 0 {
  30. return nil, fmt.Errorf("No valid challenges in the Proxy-Authenticate header")
  31. }
  32. // NTLM > Digest > Basic
  33. if challenge, ok := challenges["NTLM"]; ok {
  34. return newNTLMAuthenticator(challenge), nil
  35. } else if challenge, ok := challenges["Digest"]; ok {
  36. return newDigestAuthenticator(challenge), nil
  37. } else if challenge, ok := challenges["Basic"]; ok {
  38. return newBasicAuthenticator(challenge), nil
  39. }
  40. //Unsupported scheme
  41. schemes := make([]string, 0, len(challenges))
  42. for scheme := range challenges {
  43. schemes = append(schemes, scheme)
  44. }
  45. return nil, fmt.Errorf("Unsupported proxy authentication scheme in %v", schemes)
  46. }