Beispiel #1
0
// The Let's Encrypt state directory format keeps certificates but not their
// URLs. Since boulder uses the serial number to form the URL, we can
// reconstruct the URL. But since not even the provider association is stored,
// we have to guess.
func determineLECertificateURL(certFilename string) (string, error) {
	b, err := ioutil.ReadFile(certFilename)
	if err != nil {
		return "", err
	}

	certs, err := acmeutils.LoadCertificates(b)
	if err != nil {
		return "", err
	}

	if len(certs) == 0 {
		return "", fmt.Errorf("no certs")
	}

	c, err := x509.ParseCertificate(certs[0])
	if err != nil {
		return "", err
	}

	// Don't need directory URL, direct certificate URL load only.
	cl := acmeapi.Client{}

	_, certURL, err := acmeendpoints.CertificateToEndpointURL(&cl, c, context.TODO())
	if err != nil {
		return "", err
	}

	return certURL, nil
}
Beispiel #2
0
func TestOCSP(t *testing.T) {
	b, err := acmeutils.LoadCertificates([]byte(testOCSPCerts))
	if err != nil {
		t.Fatalf("cannot load certificates")
	}

	c0, err := x509.ParseCertificate(b[0])
	if err != nil {
		t.Fatalf("cannot parse certificate")
	}

	c1, err := x509.ParseCertificate(b[1])
	if err != nil {
		t.Fatalf("cannot parse certificate")
	}

	cl := Client{}

	res, err := cl.CheckOCSP(c0, c1, context.TODO())
	if err != nil {
		t.Fatalf("ocsp error: %v", err)
	}

	if res.Status != ocsp.Revoked {
		t.Fatalf("ocsp status should be revoked (1) but is %v", res.Status)
	}
}
Beispiel #3
0
func (s *fdbStore) validateCert(certID string, c *fdb.Collection) error {
	ss, err := fdb.String(c.Open("url"))
	if err != nil {
		return err
	}

	ss = strings.TrimSpace(ss)
	if !acmeapi.ValidURL(ss) {
		return fmt.Errorf("certificate has invalid URI")
	}

	actualCertID := determineCertificateID(ss)
	if certID != actualCertID {
		return fmt.Errorf("cert ID mismatch: %#v != %#v", certID, actualCertID)
	}

	crt := &Certificate{
		URL:               ss,
		Certificates:      nil,
		Cached:            false,
		RevocationDesired: fdb.Exists(c, "revoke"),
		Revoked:           fdb.Exists(c, "revoked"),
	}

	fullchain, err := fdb.Bytes(c.Open("fullchain"))
	if err == nil {
		certs, err := acmeutils.LoadCertificates(fullchain)
		if err != nil {
			return err
		}

		xcrt, err := x509.ParseCertificate(certs[0])
		if err != nil {
			return err
		}

		keyID := determineKeyIDFromCert(xcrt)
		crt.Key = s.keys[keyID]

		if crt.Key != nil {
			err := c.WriteLink("privkey", fdb.Link{Target: "keys/" + keyID + "/privkey"})
			if err != nil {
				return err
			}
		}

		crt.Certificates = certs
		crt.Cached = true
	}

	s.certs[certID] = crt

	return nil
}
Beispiel #4
0
func TestURL(t *testing.T) {
	_, err := ByDirectoryURL("https://unknown/directory")
	if err != ErrNotFound {
		t.Fail()
	}

	for _, tc := range urlTestCases {
		e, err := ByDirectoryURL(tc.Endpoint.DirectoryURL)
		if err != nil {
			t.Fatalf("cannot get by directory URL")
		}

		if e != tc.Endpoint {
			t.Fatalf("got wrong endpoint: %v != %v", e, tc.Endpoint)
		}

		certs, err := acmeutils.LoadCertificates([]byte(tc.Cert))
		if err != nil {
			t.Fatalf("cannot load test certificate")
		}

		c0, err := x509.ParseCertificate(certs[0])
		if err != nil {
			t.Fatalf("cannot parse certificate")
		}

		cl := acmeapi.Client{}
		e, certURL, err := CertificateToEndpointURL(&cl, c0, context.TODO())
		if err != nil {
			t.Fatalf("cannot map certificate to endpoint")
		}

		e2, err := CertificateToEndpoint(&cl, c0, context.TODO())
		if e2 != e {
			t.Fatalf("mismatch")
		}

		if e != tc.Endpoint {
			t.Fatalf("certificate mapped to wrong endpoint: %v != %v", e, tc.Endpoint)
		}

		dURL, err := CertificateURLToDirectoryURL(certURL)
		if err != nil {
			t.Fatalf("cannot map certificate URL to directory URL: %v", err)
		}

		if dURL != e.DirectoryURL {
			t.Fatalf("directory URL mismatch: %v != %v", dURL, e.DirectoryURL)
		}
	}
}