diff --git a/README.md b/README.md index d30778c..899c594 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ For technical details, you can try asking Josh (not me) or reverse engineer the
-Donations are always appreciated but never expected nor required: +I do this shit for free, sometimes to my own detriment, for no good reason. Consider donating if you appreciate this monumental waste of my time. XMR: `8BjCARiV2uB2gZTbbiMUetfRxcAYZgVM5fXxjEbpmb2nAu8ND1grazZ1EhMGdRqVerAtvEJeiy7SzA3SLXpg2CtRDtCAFfn` diff --git a/cerberus.go b/cerberus.go index 6a30e43..63f7a23 100644 --- a/cerberus.go +++ b/cerberus.go @@ -30,8 +30,6 @@ type Solution struct { Nonce uint32 // Solution nonce. This is the "answer" to the problem. Redirect string // Relative path to redirect to after Solution is accepted. - Steps int8 // Steps, as described in Challenge. - // TODO: Maybe make the redirect shit auto, idk. host *url.URL @@ -102,7 +100,6 @@ func genHashes(ctx context.Context, c Challenge) <-chan Solution { Salt: c.Salt, Nonce: nonce, Redirect: "/", // Use sensible default for placeholder, for now. - Steps: c.Steps - 1, } // Ensure we don't hang if out channel is full on ctx close. select { diff --git a/cerberus_test.go b/cerberus_test.go index 7067cb5..d56f69b 100644 --- a/cerberus_test.go +++ b/cerberus_test.go @@ -4,9 +4,11 @@ import ( "context" "errors" "fmt" + "io" "log" "net" "net/http" + "net/http/cookiejar" "strings" "testing" @@ -31,26 +33,33 @@ func solveTest(ctx context.Context, hc http.Client, host string) error { connType = "tor" } - log.Printf("Fetching new %s challenge...", connType) - c, err := NewChallenge(ctx, hc, host) - if err != nil { - return err - } - log.Printf("Challenge: %s, Difficulty: %d, Steps: %d\n", c.Salt, c.Diff, c.Steps) + steps := int8(1) - s, err := Solve(ctx, c) - if err != nil { - return err - } - log.Printf("Solution hash: %x, nonce: %d\n", s.Hash, s.Nonce) + for steps > 0 { + log.Printf("Fetching new %s challenge...", connType) + c, err := NewChallenge(ctx, hc, host) + if err != nil { + return err + } + log.Printf("Challenge: %s, Difficulty: %d, Steps: %d\n", c.Salt, c.Diff, c.Steps) + steps = c.Steps - resp, err := Submit(ctx, hc, s, "") - if err != nil { - return err - } - defer resp.Body.Close() + s, err := Solve(ctx, c) + if err != nil { + return err + } + log.Printf("Solution hash: %x, nonce: %d\n", s.Hash, s.Nonce) - log.Printf("Response: %s\n\n", resp.Header.Get("Set-Cookie")) + resp, err := Submit(ctx, hc, s, "") + if err != nil { + return err + } + + b, err := io.ReadAll(resp.Body) + log.Printf("Response: %s\n\n", b[:60]) + + resp.Body.Close() + } return nil } @@ -67,9 +76,16 @@ func newProxyTransport() *http.Transport { func TestSubmit(t *testing.T) { ctx := t.Context() - err := solveTest(ctx, http.Client{}, _TEST_HOST) + jar, err := cookiejar.New(nil) if err != nil { t.Error(err) + return + } + + err = solveTest(ctx, http.Client{Jar: jar}, _TEST_HOST) + if err != nil { + t.Error(err) + return } var dnsErr *net.DNSError diff --git a/go.mod b/go.mod index 3fe0925..9b37f82 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ -module github.com/y-a-t-s/cerberus +module gitgud.io/yats/cerberus -go 1.25.5 +go 1.25.6 require ( github.com/minio/sha256-simd v1.0.1 diff --git a/http.go b/http.go index ac44856..2e996b6 100644 --- a/http.go +++ b/http.go @@ -34,14 +34,16 @@ func NewChallenge(ctx context.Context, hc http.Client, host string) (Challenge, return Challenge{}, err } - // Update host url in case we get redirected across domains. - hc.CheckRedirect = func(req *http.Request, via []*http.Request) error { - rh := req.URL.Host - if rh != u.Host && strings.HasPrefix(rh, "kiwifarms") { - u.Host = rh - } + if hc.CheckRedirect == nil { + // Update host url in case we get redirected across domains. + hc.CheckRedirect = func(req *http.Request, via []*http.Request) error { + rh := req.URL.Host + if rh != u.Host && strings.HasPrefix(rh, "kiwifarms") { + u.Host = rh + } - return nil + return nil + } } req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil) @@ -95,31 +97,7 @@ func Submit(ctx context.Context, hc http.Client, s Solution, redirect string) (* s.Redirect = redirect } - resp, err := postSolution(ctx, hc, s) - if err != nil { - return nil, err - } - - // This feels gross, but it works. - for s.Steps > 0 { - resp.Body.Close() - - c, err := NewChallenge(ctx, hc, s.host.String()) - if err != nil { - return nil, err - } - - s, err = Solve(ctx, c) - if err != nil { - return nil, err - } - resp, err = Submit(ctx, hc, s, redirect) - if err != nil { - return nil, err - } - } - - return resp, nil + return postSolution(ctx, hc, s) } func parseHost(addr string) (*url.URL, error) { @@ -144,18 +122,7 @@ func postSolution(ctx context.Context, hc http.Client, s Solution) (*http.Respon return nil, err } - resp, err := hc.Do(req) - if err != nil { - return nil, err - } - - // TODO: Additionally verify failure from response JSON. Maybe include resp body in err type. - // Rejected solution response: status=400 body={"success":false,"reason":"invalid_solution","action":"retry"} - if resp.StatusCode == 400 { - return resp, &ErrInvalidSolution{s} - } - - return resp, nil + return hc.Do(req) } func parseTags(r io.Reader) (Challenge, error) {