challenge: implement IPv6 Happy Eyeballs again, use errors to detect this within challenge, cleanup referrer tags
This commit is contained in:
@@ -8,18 +8,33 @@ import (
|
|||||||
"git.gammaspectra.live/git/go-away/utils"
|
"git.gammaspectra.live/git/go-away/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrInvalidToken = errors.New("invalid token")
|
||||||
|
var ErrMismatchedToken = errors.New("mismatched token")
|
||||||
|
var ErrMismatchedTokenHappyEyeballs = errors.New("mismatched token: IPv4 to IPv6 upgrade detected, retrying")
|
||||||
|
|
||||||
func NewKeyVerifier() (verify VerifyFunc, issue func(key Key) string) {
|
func NewKeyVerifier() (verify VerifyFunc, issue func(key Key) string) {
|
||||||
return func(key Key, token []byte, r *http.Request) (VerifyResult, error) {
|
return func(key Key, token []byte, r *http.Request) (VerifyResult, error) {
|
||||||
expectedKey, err := hex.DecodeString(string(token))
|
expectedKey, err := hex.DecodeString(string(token))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return VerifyResultFail, err
|
return VerifyResultFail, err
|
||||||
}
|
}
|
||||||
|
if len(expectedKey) != KeySize {
|
||||||
|
return VerifyResultFail, ErrInvalidToken
|
||||||
|
}
|
||||||
if subtle.ConstantTimeCompare(key[:], expectedKey) == 1 {
|
if subtle.ConstantTimeCompare(key[:], expectedKey) == 1 {
|
||||||
return VerifyResultOK, nil
|
return VerifyResultOK, nil
|
||||||
}
|
}
|
||||||
return VerifyResultFail, errors.New("mismatched token")
|
|
||||||
|
kk := Key(expectedKey)
|
||||||
|
// IPv4 -> IPv6 Happy Eyeballs
|
||||||
|
if key.Get(KeyFlagIsIPv4) == 0 && kk.Get(KeyFlagIsIPv4) > 0 {
|
||||||
|
return VerifyResultOK, ErrMismatchedTokenHappyEyeballs
|
||||||
|
}
|
||||||
|
|
||||||
|
return VerifyResultFail, ErrMismatchedToken
|
||||||
}, func(key Key) string {
|
}, func(key Key) string {
|
||||||
return hex.EncodeToString(key[:])
|
return hex.EncodeToString(key[:])
|
||||||
}
|
}
|
||||||
@@ -95,7 +110,9 @@ func RedirectUrl(r *http.Request, reg *Registration) (*url.URL, error) {
|
|||||||
data := RequestDataFromContext(r.Context())
|
data := RequestDataFromContext(r.Context())
|
||||||
values := uri.Query()
|
values := uri.Query()
|
||||||
values.Set(QueryArgRequestId, data.Id.String())
|
values.Set(QueryArgRequestId, data.Id.String())
|
||||||
values.Set(QueryArgReferer, r.Referer())
|
if ref := r.Referer(); ref != "" {
|
||||||
|
values.Set(QueryArgReferer, r.Referer())
|
||||||
|
}
|
||||||
values.Set(QueryArgChallenge, reg.Name)
|
values.Set(QueryArgChallenge, reg.Name)
|
||||||
uri.RawQuery = values.Encode()
|
uri.RawQuery = values.Encode()
|
||||||
|
|
||||||
@@ -104,6 +121,26 @@ func RedirectUrl(r *http.Request, reg *Registration) (*url.URL, error) {
|
|||||||
|
|
||||||
func VerifyHandlerChallengeResponseFunc(state StateInterface, data *RequestData, w http.ResponseWriter, r *http.Request, verifyResult VerifyResult, err error, redirect string) {
|
func VerifyHandlerChallengeResponseFunc(state StateInterface, data *RequestData, w http.ResponseWriter, r *http.Request, verifyResult VerifyResult, err error, redirect string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Happy Eyeballs! auto retry
|
||||||
|
if errors.Is(err, ErrMismatchedTokenHappyEyeballs) {
|
||||||
|
reqUri := *r.URL
|
||||||
|
q := reqUri.Query()
|
||||||
|
|
||||||
|
ref := q.Get(QueryArgReferer)
|
||||||
|
// delete query parameters that were set by go-away
|
||||||
|
for k := range q {
|
||||||
|
if strings.HasPrefix(k, QueryArgPrefix) {
|
||||||
|
q.Del(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ref != "" {
|
||||||
|
q.Set(QueryArgReferer, ref)
|
||||||
|
}
|
||||||
|
reqUri.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
http.Redirect(w, r, reqUri.String(), http.StatusTemporaryRedirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
state.ErrorPage(w, r, http.StatusBadRequest, err, redirect)
|
state.ErrorPage(w, r, http.StatusBadRequest, err, redirect)
|
||||||
return
|
return
|
||||||
} else if !verifyResult.Ok() {
|
} else if !verifyResult.Ok() {
|
||||||
|
|||||||
Reference in New Issue
Block a user