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 TestValidateDvsni(t *testing.T) { va := NewValidationAuthorityImpl(true) va.DNSResolver = &mocks.MockDNS{} mockRA := &MockRegistrationAuthority{} va.RA = mockRA challDvsni := core.DvsniChallenge() challDvsni.S = challDvsni.R 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.StatusValid, mockRA.lastAuthz.Challenges[0].Status) }
func (va ValidationAuthorityImpl) validateDvsni(identifier core.AcmeIdentifier, input core.Challenge) (core.Challenge, error) { challenge := input if identifier.Type != "dns" { err := fmt.Errorf("Identifier type for DVSNI was not DNS") challenge.Status = core.StatusInvalid return challenge, err } const DVSNI_SUFFIX = ".acme.invalid" nonceName := challenge.Nonce + DVSNI_SUFFIX R, err := core.B64dec(challenge.R) if err != nil { va.log.Debug("Failed to decode R value from DVSNI challenge") challenge.Status = core.StatusInvalid return challenge, err } S, err := core.B64dec(challenge.S) if err != nil { va.log.Debug("Failed to decode S value from DVSNI challenge") challenge.Status = core.StatusInvalid return challenge, err } RS := append(R, S...) z := sha256.Sum256(RS) zName := fmt.Sprintf("%064x.acme.invalid", z) // Make a connection with SNI = nonceName hostPort := identifier.Value + ":443" if va.TestMode { hostPort = "localhost:5001" } va.log.Notice(fmt.Sprintf("Attempting to validate DVSNI for %s %s %s", identifier, hostPort, zName)) conn, err := tls.Dial("tcp", hostPort, &tls.Config{ ServerName: nonceName, InsecureSkipVerify: true, }) if err != nil { va.log.Debug("Failed to connect to host for DVSNI challenge") challenge.Status = core.StatusInvalid return challenge, err } defer conn.Close() // Check that zName is a dNSName SAN in the server's certificate certs := conn.ConnectionState().PeerCertificates if len(certs) == 0 { err = fmt.Errorf("No certs presented for DVSNI challenge") challenge.Status = core.StatusInvalid return challenge, err } for _, name := range certs[0].DNSNames { if subtle.ConstantTimeCompare([]byte(name), []byte(zName)) == 1 { challenge.Status = core.StatusValid return challenge, nil } } err = fmt.Errorf("Correct zName not found for DVSNI challenge") challenge.Status = core.StatusInvalid return challenge, err }
func (va ValidationAuthorityImpl) validateDvsni(identifier core.AcmeIdentifier, input core.Challenge) (core.Challenge, error) { challenge := input if identifier.Type != "dns" { challenge.Error = &core.ProblemDetails{ Type: core.MalformedProblem, Detail: "Identifier type for DVSNI was not DNS", } challenge.Status = core.StatusInvalid va.log.Debug(fmt.Sprintf("DVSNI [%s] Identifier failure", identifier)) return challenge, challenge.Error } const DVSNIsuffix = ".acme.invalid" nonceName := challenge.Nonce + DVSNIsuffix R, err := core.B64dec(challenge.R) if err != nil { challenge.Status = core.StatusInvalid challenge.Error = &core.ProblemDetails{ Type: core.MalformedProblem, Detail: "Failed to decode R value from DVSNI challenge", } va.log.Debug(fmt.Sprintf("DVSNI [%s] R Decode failure: %s", identifier, err)) return challenge, err } S, err := core.B64dec(challenge.S) if err != nil { challenge.Status = core.StatusInvalid challenge.Error = &core.ProblemDetails{ Type: core.MalformedProblem, Detail: "Failed to decode S value from DVSNI challenge", } va.log.Debug(fmt.Sprintf("DVSNI [%s] S Decode failure: %s", identifier, err)) return challenge, err } RS := append(R, S...) z := sha256.Sum256(RS) zName := fmt.Sprintf("%064x.acme.invalid", z) // Make a connection with SNI = nonceName hostPort := identifier.Value + ":443" if va.TestMode { hostPort = "localhost:5001" } va.log.Notice(fmt.Sprintf("DVSNI [%s] Attempting to validate DVSNI for %s %s", identifier, hostPort, zName)) conn, err := tls.DialWithDialer(&net.Dialer{Timeout: 5 * time.Second}, "tcp", hostPort, &tls.Config{ ServerName: nonceName, InsecureSkipVerify: true, }) if err != nil { challenge.Status = core.StatusInvalid challenge.Error = &core.ProblemDetails{ Type: parseHTTPConnError(err), Detail: "Failed to connect to host for DVSNI challenge", } va.log.Debug(fmt.Sprintf("DVSNI [%s] TLS Connection failure: %s", identifier, err)) return challenge, err } defer conn.Close() // Check that zName is a dNSName SAN in the server's certificate certs := conn.ConnectionState().PeerCertificates if len(certs) == 0 { challenge.Error = &core.ProblemDetails{ Type: core.UnauthorizedProblem, Detail: "No certs presented for DVSNI challenge", } challenge.Status = core.StatusInvalid return challenge, challenge.Error } for _, name := range certs[0].DNSNames { if subtle.ConstantTimeCompare([]byte(name), []byte(zName)) == 1 { challenge.Status = core.StatusValid return challenge, nil } } challenge.Error = &core.ProblemDetails{ Type: core.UnauthorizedProblem, Detail: "Correct zName not found for DVSNI challenge", } challenge.Status = core.StatusInvalid return challenge, challenge.Error }