func TestSimpleHttpRedirectLookup(t *testing.T) { tls := false chall := core.Challenge{ Token: expectedToken, TLS: &tls, ValidationRecord: []core.ValidationRecord{}, AccountKey: accountKey, } hs := simpleSrv(t, expectedToken, tls) defer hs.Close() port, err := getPort(hs) test.AssertNotError(t, err, "failed to get test server port") va := NewValidationAuthorityImpl(&PortConfig{SimpleHTTPPort: port}) va.DNSResolver = &mocks.MockDNS{} log.Clear() chall.Token = pathMoved finChall, err := va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 2) log.Clear() chall.Token = pathFound finChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 3) log.Clear() chall.Token = pathRedirectLookupInvalid finChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`No IPv4 addresses found for invalid.invalid`)), 1) log.Clear() chall.Token = pathRedirectLookup finChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/re-lookup" to ".*other.valid/path"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for other.valid \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) log.Clear() chall.Token = pathRedirectPort finChall, err = va.validateSimpleHTTP(ident, chall) fmt.Println(finChall.ValidationRecord) test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/port-redirect" to ".*other.valid:8080/path"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for other.valid \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) }
func TestSimpleHttpRedirectLookup(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = &mocks.MockDNS{} tls := false chall := core.Challenge{Token: expectedToken, TLS: &tls, ValidationRecord: []core.ValidationRecord{}} stopChan := make(chan bool, 1) waitChan := make(chan bool, 1) go simpleSrv(t, expectedToken, stopChan, waitChan, tls) defer func() { stopChan <- true }() <-waitChan log.Clear() chall.Token = pathMoved finChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 2) log.Clear() chall.Token = pathFound finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 3) log.Clear() chall.Token = pathRedirectLookupInvalid finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`No IPv4 addresses found for invalid.invalid`)), 1) log.Clear() chall.Token = pathRedirectLookup finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/re-lookup" to ".*other.valid/path"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for other.valid \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) log.Clear() chall.Token = pathRedirectPort finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) fmt.Println(finChall.ValidationRecord) test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertError(t, err, chall.Token) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/port-redirect" to ".*other.valid:8080/path"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for other.valid \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) }
// setChallengeToken sets the token value both in the Token field and // in the serialized KeyAuthorization object. func setChallengeToken(ch *core.Challenge, token string) { ch.Token = token ka, err := ch.ExpectedKeyAuthorization() if err != nil { panic(err) } ch.ProvidedKeyAuthorization = ka }
// setChallengeToken sets the token value both in the Token field and // in the serialized KeyAuthorization object. func setChallengeToken(ch *core.Challenge, token string) (err error) { ch.Token = token keyAuthorization, err := core.NewKeyAuthorization(token, ch.AccountKey) if err != nil { return } ch.KeyAuthorization = &keyAuthorization return }
// TODO(https://github.com/letsencrypt/boulder/issues/894): Remove this method func TestSimpleHttp(t *testing.T) { tls := false chall := core.Challenge{ Type: core.ChallengeTypeSimpleHTTP, Token: expectedToken, TLS: &tls, ValidationRecord: []core.ValidationRecord{}, AccountKey: accountKey, } // NOTE: We do not attempt to shut down the server. The problem is that the // "wait-long" handler sleeps for ten seconds, but this test finishes in less // than that. So if we try to call hs.Close() at the end of the test, we'll be // closing the test server while a request is still pending. Unfortunately, // there appears to be an issue in httptest that trips Go's race detector when // that happens, failing the test. So instead, we live with leaving the server // around till the process exits. // TODO(#661): add hs.Close back, see ticket for blocker hs := simpleSrv(t, expectedToken, tls) goodPort, err := getPort(hs) test.AssertNotError(t, err, "failed to get test server port") // Attempt to fail a challenge by telling the VA to connect to a port we are // not listening on. badPort := goodPort + 1 if badPort == 65536 { badPort = goodPort - 1 } stats, _ := statsd.NewNoopClient() va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: badPort}, nil, stats, clock.Default()) va.DNSResolver = &mocks.DNSResolver{} invalidChall, err := va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Server's down; expected refusal. Where did we connect?") test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem) va = NewValidationAuthorityImpl(&PortConfig{HTTPPort: goodPort}, nil, stats, clock.Default()) va.DNSResolver = &mocks.DNSResolver{} log.Clear() finChall, err := va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "Error validating simpleHttp") test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) log.Clear() chall.Token = path404 invalidChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Should have found a 404 for the challenge.") test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) log.Clear() chall.Token = pathWrongToken // The "wrong token" will actually be the expectedToken. It's wrong // because it doesn't match pathWrongToken. invalidChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Should have found the wrong token value.") test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) log.Clear() chall.Token = pathMoved finChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "Failed to follow 301 redirect") test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/`+pathMoved+`" to ".*/`+pathValid+`"`)), 1) log.Clear() chall.Token = pathFound finChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "Failed to follow 302 redirect") test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/`+pathFound+`" to ".*/`+pathMoved+`"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/`+pathMoved+`" to ".*/`+pathValid+`"`)), 1) ipIdentifier := core.AcmeIdentifier{Type: core.IdentifierType("ip"), Value: "127.0.0.1"} invalidChall, err = va.validateSimpleHTTP(ipIdentifier, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "IdentifierType IP shouldn't have worked.") test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) invalidChall, err = va.validateSimpleHTTP(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "always.invalid"}, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Domain name is invalid.") test.AssertEquals(t, invalidChall.Error.Type, core.UnknownHostProblem) chall.Token = "wait-long" started := time.Now() invalidChall, err = va.validateSimpleHTTP(ident, chall) took := time.Since(started) // Check that the HTTP connection times out after 5 seconds and doesn't block for 10 seconds test.Assert(t, (took > (time.Second * 5)), "HTTP timed out before 5 seconds") test.Assert(t, (took < (time.Second * 10)), "HTTP connection didn't timeout after 5 seconds") test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Connection should've timed out") test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem) }
func TestSimpleHttp(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = &mocks.MockDNS{} tls := false chall := core.Challenge{Type: core.ChallengeTypeSimpleHTTP, Token: expectedToken, TLS: &tls} invalidChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Server's not up yet; expected refusal. Where did we connect?") test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem) stopChan := make(chan bool, 1) waitChan := make(chan bool, 1) go simpleSrv(t, expectedToken, stopChan, waitChan, tls) defer func() { stopChan <- true }() <-waitChan log.Clear() finChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "Error validating simpleHttp") test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) log.Clear() chall.Token = path404 invalidChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Should have found a 404 for the challenge.") test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) log.Clear() chall.Token = pathWrongToken // The "wrong token" will actually be the expectedToken. It's wrong // because it doesn't match pathWrongToken. invalidChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Should have found the wrong token value.") test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) log.Clear() chall.Token = pathMoved finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "Failed to follow 301 redirect") test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) log.Clear() chall.Token = pathFound finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "Failed to follow 302 redirect") test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) ipIdentifier := core.AcmeIdentifier{Type: core.IdentifierType("ip"), Value: "127.0.0.1"} invalidChall, err = va.validateSimpleHTTP(ipIdentifier, chall, AccountKey) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "IdentifierType IP shouldn't have worked.") test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) va.TestMode = false invalidChall, err = va.validateSimpleHTTP(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "always.invalid"}, chall, AccountKey) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Domain name is invalid.") test.AssertEquals(t, invalidChall.Error.Type, core.UnknownHostProblem) va.TestMode = true chall.Token = "wait-long" started := time.Now() invalidChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) took := time.Since(started) // Check that the HTTP connection times out after 5 seconds and doesn't block for 10 seconds test.Assert(t, (took > (time.Second * 5)), "HTTP timed out before 5 seconds") test.Assert(t, (took < (time.Second * 10)), "HTTP connection didn't timeout after 5 seconds") test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Connection should've timed out") test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem) }
// setChallengeToken sets the token value, and sets the ProvidedKeyAuthorization // to match. func setChallengeToken(ch *core.Challenge, token string) { ch.Token = token ch.ProvidedKeyAuthorization = token + ".9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI" }