216 lines
7.7 KiB
Go
216 lines
7.7 KiB
Go
// Copyright 2014 ISRG. All rights reserved
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package policy
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/square/go-jose"
|
|
|
|
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
|
"github.com/letsencrypt/boulder/core"
|
|
"github.com/letsencrypt/boulder/mocks"
|
|
"github.com/letsencrypt/boulder/sa"
|
|
"github.com/letsencrypt/boulder/test"
|
|
"github.com/letsencrypt/boulder/test/vars"
|
|
)
|
|
|
|
var log = mocks.UseMockLog()
|
|
|
|
var enabledChallenges = map[string]bool{
|
|
core.ChallengeTypeHTTP01: true,
|
|
core.ChallengeTypeTLSSNI01: true,
|
|
core.ChallengeTypeDNS01: true,
|
|
}
|
|
|
|
func paImpl(t *testing.T) (*AuthorityImpl, func()) {
|
|
dbMap, cleanUp := paDBMap(t)
|
|
pa, err := New(dbMap, false, enabledChallenges)
|
|
if err != nil {
|
|
cleanUp()
|
|
t.Fatalf("Couldn't create policy implementation: %s", err)
|
|
}
|
|
return pa, cleanUp
|
|
}
|
|
|
|
func paDBMap(t *testing.T) (*gorp.DbMap, func()) {
|
|
dbMap, err := sa.NewDbMap(vars.DBConnPolicy)
|
|
test.AssertNotError(t, err, "Could not construct dbMap")
|
|
cleanUp := test.ResetPolicyTestDatabase(t)
|
|
return dbMap, cleanUp
|
|
}
|
|
|
|
func TestWillingToIssue(t *testing.T) {
|
|
testCases := []struct {
|
|
domain string
|
|
err error
|
|
}{
|
|
{``, errEmptyName}, // Empty name
|
|
{`zomb!.com`, errInvalidDNSCharacter}, // ASCII character out of range
|
|
{`emailaddress@myseriously.present.com`, errInvalidDNSCharacter},
|
|
{`user:pass@myseriously.present.com`, errInvalidDNSCharacter},
|
|
{`zömbo.com`, errInvalidDNSCharacter}, // non-ASCII character
|
|
{`127.0.0.1`, errIPAddress}, // IPv4 address
|
|
{`fe80::1:1`, errInvalidDNSCharacter}, // IPv6 addresses
|
|
{`[2001:db8:85a3:8d3:1319:8a2e:370:7348]`, errInvalidDNSCharacter}, // unexpected IPv6 variants
|
|
{`[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443`, errInvalidDNSCharacter},
|
|
{`2001:db8::/32`, errInvalidDNSCharacter},
|
|
{`a.b.c.d.e.f.g.h.i.j.k`, errTooManyLabels}, // Too many labels (>10)
|
|
|
|
{`www.0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef.com`, errNameTooLong}, // Too long (>255 characters)
|
|
|
|
{`www.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.com`, errLabelTooLong}, // Label too long (>63 characters)
|
|
|
|
{`www.-ombo.com`, errInvalidDNSCharacter}, // Label starts with '-'
|
|
{`www.zomb-.com`, errInvalidDNSCharacter}, // Label ends with '-'
|
|
{`xn--.net`, errInvalidDNSCharacter}, // Label ends with '-'
|
|
{`www.xn--hmr.net`, errIDNNotSupported}, // Punycode (disallowed for now)
|
|
{`0`, errTooFewLabels},
|
|
{`1`, errTooFewLabels},
|
|
{`*`, errInvalidDNSCharacter},
|
|
{`**`, errInvalidDNSCharacter},
|
|
{`*.*`, errInvalidDNSCharacter},
|
|
{`zombo*com`, errInvalidDNSCharacter},
|
|
{`*.com`, errInvalidDNSCharacter},
|
|
{`*.zombo.com`, errInvalidDNSCharacter},
|
|
{`.`, errLabelTooShort},
|
|
{`..`, errLabelTooShort},
|
|
{`a..`, errLabelTooShort},
|
|
{`..a`, errLabelTooShort},
|
|
{`.a.`, errLabelTooShort},
|
|
{`.....`, errLabelTooShort},
|
|
{`www.zombo_com.com`, errInvalidDNSCharacter},
|
|
{`\uFEFF`, errInvalidDNSCharacter}, // Byte order mark
|
|
{`\uFEFFwww.zombo.com`, errInvalidDNSCharacter},
|
|
{`www.zom\u202Ebo.com`, errInvalidDNSCharacter}, // Right-to-Left Override
|
|
{`\u202Ewww.zombo.com`, errInvalidDNSCharacter},
|
|
{`www.zom\u200Fbo.com`, errInvalidDNSCharacter}, // Right-to-Left Mark
|
|
{`\u200Fwww.zombo.com`, errInvalidDNSCharacter},
|
|
// Underscores are technically disallowed in DNS. Some DNS
|
|
// implementations accept them but we will be conservative.
|
|
{`www.zom_bo.com`, errInvalidDNSCharacter},
|
|
{`zombocom`, errTooFewLabels},
|
|
{`localhost`, errTooFewLabels},
|
|
{`mail`, errTooFewLabels},
|
|
|
|
// disallow capitalized letters for #927
|
|
{`CapitalizedLetters.com`, errInvalidDNSCharacter},
|
|
|
|
{`example.acting`, errNonPublic},
|
|
{`example.internal`, errNonPublic},
|
|
// All-numeric final label not okay.
|
|
{`www.zombo.163`, errNonPublic},
|
|
}
|
|
|
|
shouldBeTLDError := []string{
|
|
`co.uk`,
|
|
`foo.bn`,
|
|
}
|
|
|
|
shouldBeBlacklisted := []string{
|
|
`addons.mozilla.org`,
|
|
`ebay.co.uk`,
|
|
`www.google.com`,
|
|
`lots.of.labels.pornhub.com`,
|
|
}
|
|
|
|
shouldBeAccepted := []string{
|
|
"www.zombo.com",
|
|
"zombo.com",
|
|
"www.8675309.com",
|
|
"8675309.com",
|
|
"zom2bo.com",
|
|
"www.zom-bo.com",
|
|
}
|
|
|
|
pa, cleanup := paImpl(t)
|
|
defer cleanup()
|
|
|
|
rules := RuleSet{}
|
|
for _, b := range shouldBeBlacklisted {
|
|
rules.Blacklist = append(rules.Blacklist, BlacklistRule{Host: b})
|
|
}
|
|
err := pa.DB.LoadRules(rules)
|
|
test.AssertNotError(t, err, "Couldn't load rules")
|
|
|
|
// Test for invalid identifier type
|
|
identifier := core.AcmeIdentifier{Type: "ip", Value: "example.com"}
|
|
err = pa.WillingToIssue(identifier, 100)
|
|
if err != errInvalidIdentifier {
|
|
t.Error("Identifier was not correctly forbidden: ", identifier)
|
|
}
|
|
|
|
// Test syntax errors
|
|
for _, tc := range testCases {
|
|
identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: tc.domain}
|
|
err := pa.WillingToIssue(identifier, 100)
|
|
if err != tc.err {
|
|
t.Errorf("WillingToIssue(%q) = %q, expected %q", tc.domain, err, tc.err)
|
|
}
|
|
}
|
|
|
|
// Test domains that are equal to public suffixes
|
|
for _, domain := range shouldBeTLDError {
|
|
identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: domain}
|
|
err := pa.WillingToIssue(identifier, 100)
|
|
if err != errICANNTLD {
|
|
t.Error("Identifier was not correctly forbidden: ", identifier, err)
|
|
}
|
|
}
|
|
|
|
// Test blacklisting
|
|
for _, domain := range shouldBeBlacklisted {
|
|
identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: domain}
|
|
err := pa.WillingToIssue(identifier, 100)
|
|
if err != errBlacklisted {
|
|
t.Error("Identifier was not correctly forbidden: ", identifier, err)
|
|
}
|
|
}
|
|
|
|
// Test acceptance of good names
|
|
for _, domain := range shouldBeAccepted {
|
|
identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: domain}
|
|
if err := pa.WillingToIssue(identifier, 100); err != nil {
|
|
t.Error("Identifier was incorrectly forbidden: ", identifier, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
var accountKeyJSON = `{
|
|
"kty":"RSA",
|
|
"n":"yNWVhtYEKJR21y9xsHV-PD_bYwbXSeNuFal46xYxVfRL5mqha7vttvjB_vc7Xg2RvgCxHPCqoxgMPTzHrZT75LjCwIW2K_klBYN8oYvTwwmeSkAz6ut7ZxPv-nZaT5TJhGk0NT2kh_zSpdriEJ_3vW-mqxYbbBmpvHqsa1_zx9fSuHYctAZJWzxzUZXykbWMWQZpEiE0J4ajj51fInEzVn7VxV-mzfMyboQjujPh7aNJxAWSq4oQEJJDgWwSh9leyoJoPpONHxh5nEE5AjE01FkGICSxjpZsF-w8hOTI3XXohUdu29Se26k2B0PolDSuj0GIQU6-W9TdLXSjBb2SpQ",
|
|
"e":"AQAB"
|
|
}`
|
|
|
|
func TestChallengesFor(t *testing.T) {
|
|
pa, cleanup := paImpl(t)
|
|
defer cleanup()
|
|
|
|
var accountKey *jose.JsonWebKey
|
|
err := json.Unmarshal([]byte(accountKeyJSON), &accountKey)
|
|
if err != nil {
|
|
t.Errorf("Error unmarshaling JWK: %v", err)
|
|
}
|
|
|
|
challenges, combinations := pa.ChallengesFor(core.AcmeIdentifier{}, accountKey)
|
|
|
|
test.Assert(t, len(challenges) == len(enabledChallenges), "Wrong number of challenges returned")
|
|
test.Assert(t, len(combinations) == len(enabledChallenges), "Wrong number of combinations returned")
|
|
|
|
seenChalls := make(map[string]bool)
|
|
// Expected only if the pseudo-RNG is seeded with 99.
|
|
expectedCombos := [][]int{{1}, {2}, {0}}
|
|
for _, challenge := range challenges {
|
|
test.Assert(t, !seenChalls[challenge.Type], "should not already have seen this type")
|
|
seenChalls[challenge.Type] = true
|
|
|
|
test.Assert(t, enabledChallenges[challenge.Type], "Unsupported challenge returned")
|
|
}
|
|
test.AssertEquals(t, len(seenChalls), len(enabledChallenges))
|
|
test.AssertDeepEquals(t, expectedCombos, combinations)
|
|
}
|