func TestDNSValidationInvalid(t *testing.T) { var notDNS = core.AcmeIdentifier{ Type: core.IdentifierType("iris"), Value: "790DB180-A274-47A4-855F-31C428CB1072", } chalDNS := core.DNSChallenge() var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: notDNS, Challenges: []core.Challenge{chalDNS}, } va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA va.validate(authz, 0) test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.AssertEquals(t, authz.Challenges[0].Error.Type, core.MalformedProblem) }
func TestUpdateValidations(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA challHTTP := core.SimpleHTTPChallenge() challHTTP.Path = "wait" stopChanHTTP := make(chan bool, 1) waitChanHTTP := make(chan bool, 1) go simpleSrv(t, challHTTP.Token, stopChanHTTP, waitChanHTTP) // Let them start <-waitChanHTTP // shutdown cleanly defer func() { stopChanHTTP <- true }() var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: ident, Challenges: []core.Challenge{challHTTP}, } started := time.Now() va.UpdateValidations(authz, 0) took := time.Since(started) // Check that the call to va.UpdateValidations didn't block for 3 seconds test.Assert(t, (took < (time.Second * 3)), "UpdateValidations blocked") }
func TestValidateHTTP(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA challHTTP := core.SimpleHTTPChallenge() challHTTP.Path = "test" stopChanHTTP := make(chan bool, 1) waitChanHTTP := make(chan bool, 1) go simpleSrv(t, challHTTP.Token, stopChanHTTP, waitChanHTTP) // Let them start <-waitChanHTTP // shutdown cleanly defer func() { stopChanHTTP <- true }() var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: ident, Challenges: []core.Challenge{challHTTP}, } va.validate(authz, 0) test.AssertEquals(t, core.StatusValid, mockRA.lastAuthz.Challenges[0].Status) }
func TestValidateDvsniNotSane(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA challDvsni := core.DvsniChallenge() challDvsni.R = "boulder" // Not a sane thing to do. waitChanDvsni := make(chan bool, 1) stopChanDvsni := make(chan bool, 1) ar, _ := core.B64dec(challDvsni.R) as, _ := core.B64dec(challDvsni.S) go dvsniSrv(t, ar, as, stopChanDvsni, waitChanDvsni) // Let them start <-waitChanDvsni // shutdown cleanly defer func() { stopChanDvsni <- true }() var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: ident, Challenges: []core.Challenge{challDvsni}, } va.validate(authz, 0) test.AssertEquals(t, core.StatusInvalid, mockRA.lastAuthz.Challenges[0].Status) }
func TestDvsni(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) a := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0} ba := core.B64enc(a) chall := core.Challenge{R: ba, S: ba} invalidChall, err := va.validateDvsni(ident, chall) 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) waitChan := make(chan bool, 1) stopChan := make(chan bool, 1) go dvsniSrv(t, a, a, stopChan, waitChan) defer func() { stopChan <- true }() <-waitChan finChall, err := va.validateDvsni(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, "") invalidChall, err = va.validateDvsni(core.AcmeIdentifier{Type: core.IdentifierType("ip"), Value: "127.0.0.1"}, 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) va.TestMode = false invalidChall, err = va.validateDvsni(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) va.TestMode = true chall.R = ba[5:] invalidChall, err = va.validateDvsni(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "R Should be illegal Base64") test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) chall.R = ba chall.S = "!@#" invalidChall, err = va.validateDvsni(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "S Should be illegal Base64") test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) chall.S = ba chall.Nonce = "wait-long" started := time.Now() invalidChall, err = va.validateDvsni(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) }
// TestDNSValidationLive is an integration test, depending on // the existance of some Internet resources. Because of that, // it asserts nothing; it is intended for coverage. func TestDNSValidationLive(t *testing.T) { va := NewValidationAuthorityImpl(false) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA goodChalDNS := core.DNSChallenge() // This token is set at _acme-challenge.good.bin.coffee goodChalDNS.Token = "yfCBb-bRTLz8Wd1C0lTUQK3qlKj3-t2tYGwx5Hj7r_w" var goodIdent = core.AcmeIdentifier{ Type: core.IdentifierDNS, Value: "good.bin.coffee", } var badIdent = core.AcmeIdentifier{ Type: core.IdentifierType("dns"), Value: "bad.bin.coffee", } var authzGood = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: goodIdent, Challenges: []core.Challenge{goodChalDNS}, } va.validate(authzGood, 0) if authzGood.Challenges[0].Status != core.StatusValid { t.Logf("TestDNSValidationLive on Good did not succeed.") } badChalDNS := core.DNSChallenge() // This token is NOT set at _acme-challenge.bad.bin.coffee badChalDNS.Token = "yfCBb-bRTLz8Wd1C0lTUQK3qlKj3-t2tYGwx5Hj7r_w" var authzBad = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: badIdent, Challenges: []core.Challenge{badChalDNS}, } va.validate(authzBad, 0) if authzBad.Challenges[0].Status != core.StatusInvalid { t.Logf("TestDNSValidationLive on Bad did succeed inappropriately.") } }
func main() { app := cmd.NewAppShell("boulder-va") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.ProfileCmd("VA", stats) vai := va.NewValidationAuthorityImpl(c.CA.TestMode) dnsTimeout, err := time.ParseDuration(c.VA.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") vai.DNSResolver = core.NewDNSResolver(dnsTimeout, []string{c.VA.DNSResolver}) vai.UserAgent = c.VA.UserAgent for { ch, err := cmd.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) raRPC, err := rpc.NewAmqpRPCClient("VA->RA", c.AMQP.RA.Server, ch) cmd.FailOnError(err, "Unable to create RPC client") rac, err := rpc.NewRegistrationAuthorityClient(raRPC) cmd.FailOnError(err, "Unable to create RA client") vai.RA = &rac vas := rpc.NewAmqpRPCServer(c.AMQP.VA.Server, ch) err = rpc.NewValidationAuthorityServer(vas, &vai) cmd.FailOnError(err, "Unable to create VA server") auditlogger.Info(app.VersionString()) cmd.RunUntilSignaled(auditlogger, vas, closeChan) } } app.Run() }
func TestCAAChecking(t *testing.T) { type CAATest struct { Domain string Present bool Valid bool } tests := []CAATest{ // Reserved CAATest{"google.com", true, false}, CAATest{"mail.google.com", true, false}, CAATest{"*.google.com", true, false}, CAATest{"comodo.com", true, false}, CAATest{"0day.net", true, false}, CAATest{"darktangent.org", true, false}, CAATest{"instantssl.com", true, false}, CAATest{"nails.eu.org", true, false}, // Critical CAATest{"goop.org", true, false}, CAATest{"nethemba.com", true, false}, CAATest{"arrakis.tv", true, false}, CAATest{"mail2.bevenhall.se", true, false}, // Good (absent) CAATest{"linux.org", false, true}, CAATest{"*.linux.org", false, true}, CAATest{"pir.org", false, true}, CAATest{"non-existent-domain-really.com", false, true}, // Good (present, none of my DNS providers support CAA currently) // CAATest{"letsencrypt.org", true, true}, } va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) for _, caaTest := range tests { present, valid, err := va.CheckCAARecords(core.AcmeIdentifier{Type: "dns", Value: caaTest.Domain}) // Ignore tests if DNS req has timed out if err != nil && err.Error() == "read udp 8.8.8.8:53: i/o timeout" { continue } test.AssertNotError(t, err, caaTest.Domain) fmt.Println(caaTest.Domain) test.AssertEquals(t, caaTest.Present, present) test.AssertEquals(t, caaTest.Valid, valid) } present, valid, err := va.CheckCAARecords(core.AcmeIdentifier{Type: "dns", Value: "dnssec-failed.org"}) test.AssertError(t, err, "dnssec-failed.org") test.Assert(t, !present, "Present should be false") test.Assert(t, !valid, "Valid should be false") }
func TestDNSValidationNoServer(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA chalDNS := core.DNSChallenge() var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: ident, Challenges: []core.Challenge{chalDNS}, } va.validate(authz, 0) test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.AssertEquals(t, authz.Challenges[0].Error.Type, core.ServerInternalProblem) }
func TestTLSError(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) a := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0} ba := core.B64enc(a) chall := core.Challenge{R: ba, S: ba} waitChan := make(chan bool, 1) stopChan := make(chan bool, 1) go brokenTLSSrv(t, stopChan, waitChan) defer func() { stopChan <- true }() <-waitChan invalidChall, err := va.validateDvsni(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "What cert was used?") test.AssertEquals(t, invalidChall.Error.Type, core.TLSProblem) }
func TestDNSValidationNotSane(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA chal0 := core.DNSChallenge() chal0.Token = "" chal1 := core.DNSChallenge() chal1.Token = "yfCBb-bRTLz8Wd1C0lTUQK3qlKj3-t2tYGwx5Hj7r_" chal2 := core.DNSChallenge() chal2.R = "1" chal3 := core.DNSChallenge() chal3.S = "2" chal4 := core.DNSChallenge() chal4.Nonce = "2" chal5 := core.DNSChallenge() var tls = true chal5.TLS = &tls var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: ident, Challenges: []core.Challenge{chal0, chal1, chal2, chal3, chal4, chal5}, } for i := 0; i < 6; i++ { va.validate(authz, i) test.AssertEquals(t, authz.Challenges[i].Status, core.StatusInvalid) test.AssertEquals(t, authz.Challenges[i].Error.Type, core.MalformedProblem) } }
func TestDNSValidationBadDNSSEC(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) mockRA := &MockRegistrationAuthority{} va.RA = mockRA chalDNS := core.DNSChallenge() badDNSSEC := core.AcmeIdentifier{ Type: core.IdentifierDNS, Value: "dnssec-failed.org", } var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: badDNSSEC, Challenges: []core.Challenge{chalDNS}, } va.validate(authz, 0) test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.AssertEquals(t, authz.Challenges[0].Error.Type, core.DNSSECProblem) }
func TestSimpleHttp(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = core.NewDNSResolver(time.Second*5, []string{"8.8.8.8:53"}) chall := core.Challenge{Path: "test", Token: expectedToken} invalidChall, err := va.validateSimpleHTTP(ident, chall) 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) defer func() { stopChan <- true }() <-waitChan finChall, err := va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Path) tls := false chall.TLS = &tls finChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertNotError(t, err, chall.Path) tls = true chall.TLS = &tls chall.Path = 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) chall.Path = pathWrongToken invalidChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "The path should have given us the wrong token.") test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) chall.Path = "" invalidChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Empty paths shouldn't work either.") test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) chall.Path = "validish" invalidChall, err = va.validateSimpleHTTP(core.AcmeIdentifier{Type: core.IdentifierType("ip"), Value: "127.0.0.1"}, 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) va.TestMode = false chall.Path = "alsoValidish" 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) va.TestMode = true chall.Path = "%" invalidChall, err = va.validateSimpleHTTP(ident, chall) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertError(t, err, "Path doesn't consist of URL-safe characters.") test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) chall.Path = "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 main() { app := cmd.NewAppShell("boulder") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) // Run StatsD profiling go cmd.ProfileCmd("Monolith", stats) // Create the components wfei, err := wfe.NewWebFrontEndImpl() cmd.FailOnError(err, "Unable to create WFE") sa, err := sa.NewSQLStorageAuthority(c.SA.DBDriver, c.SA.DBName) cmd.FailOnError(err, "Unable to create SA") sa.SetSQLDebug(c.SQL.SQLDebug) ra := ra.NewRegistrationAuthorityImpl() va := va.NewValidationAuthorityImpl(c.CA.TestMode) dnsTimeout, err := time.ParseDuration(c.VA.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") va.DNSResolver = core.NewDNSResolver(dnsTimeout, []string{c.VA.DNSResolver}) va.UserAgent = c.VA.UserAgent cadb, err := ca.NewCertificateAuthorityDatabaseImpl(c.CA.DBDriver, c.CA.DBName) cmd.FailOnError(err, "Failed to create CA database") ca, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, c.Common.IssuerCert) cmd.FailOnError(err, "Unable to create CA") if c.SQL.CreateTables { err = sa.CreateTablesIfNotExists() cmd.FailOnError(err, "Failed to create SA tables") err = cadb.CreateTablesIfNotExists() cmd.FailOnError(err, "Failed to create CA tables") } // Wire them up wfei.RA = &ra wfei.SA = sa wfei.Stats = stats wfei.SubscriberAgreementURL = c.SubscriberAgreementURL wfei.IssuerCert, err = cmd.LoadCert(c.Common.IssuerCert) cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert)) ra.CA = ca ra.SA = sa ra.VA = &va va.RA = &ra ca.SA = sa // Set up paths ra.AuthzBase = c.Common.BaseURL + wfe.AuthzPath wfei.BaseURL = c.Common.BaseURL wfei.HandlePaths() ra.MaxKeySize = c.Common.MaxKeySize ca.MaxKeySize = c.Common.MaxKeySize auditlogger.Info(app.VersionString()) fmt.Fprintf(os.Stderr, "Server running, listening on %s...\n", c.WFE.ListenAddress) err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(http.DefaultServeMux, stats)) cmd.FailOnError(err, "Error starting HTTP server") } app.Run() }