Beispiel #1
0
func (s *Store) validateKey(keyID string, kc *fdb.Collection) error {
	f, err := kc.Open("privkey")
	if err != nil {
		return err
	}

	defer f.Close()

	b, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}

	pk, err := acmeutils.LoadPrivateKey(b)
	if err != nil {
		return err
	}

	actualKeyID, err := determineKeyIDFromKey(pk)
	if err != nil {
		return err
	}

	if actualKeyID != keyID {
		return fmt.Errorf("key ID mismatch: %#v != %#v", keyID, actualKeyID)
	}

	k := &Key{
		ID: actualKeyID,
	}

	s.keys[actualKeyID] = k

	return nil
}
Beispiel #2
0
func (s *fdbStore) validateAuthorization(account *Account, authName string, c *fdb.Collection) error {
	ss, err := fdb.String(c.Open("expiry"))
	if err != nil {
		return err
	}

	expiry, err := time.Parse(time.RFC3339, strings.TrimSpace(ss))
	if err != nil {
		return err
	}

	azURL, _ := fdb.String(c.Open("url"))
	if !acmeapi.ValidURL(azURL) {
		azURL = ""
	}

	az := &Authorization{
		Name:    authName,
		URL:     strings.TrimSpace(azURL),
		Expires: expiry,
	}

	account.Authorizations[authName] = az
	return nil
}
Beispiel #3
0
// Save a private key inside a key ID collection under the given collection.
func (s *fdbStore) saveKeyUnderID(c *fdb.Collection, privateKey crypto.PrivateKey) (keyID string, err error) {
	keyID, err = determineKeyIDFromKey(privateKey)
	if err != nil {
		return
	}

	err = s.saveKey(c.Collection(keyID), privateKey)
	return
}
Beispiel #4
0
// Saves a key as a file named "privkey" inside the given collection.
func (s *fdbStore) saveKey(c *fdb.Collection, privateKey crypto.PrivateKey) error {
	f, err := c.Create("privkey")
	if err != nil {
		return err
	}
	defer f.CloseAbort()

	err = acmeutils.SavePrivateKey(f, privateKey)
	if err != nil {
		return err
	}

	return f.Close()
}
Beispiel #5
0
func (s *Store) validateTargetInner(desiredKey string, c *fdb.Collection, loadingDefault bool) (*Target, error) {
	b, err := fdb.Bytes(c.Open(desiredKey))
	if err != nil {
		return nil, err
	}

	var tgt *Target
	if loadingDefault {
		tgt = &Target{}
	} else {
		tgt = s.defaultTarget.CopyGeneric()
	}

	err = yaml.Unmarshal(b, tgt)
	if err != nil {
		return nil, err
	}

	if len(tgt.Satisfy.Names) == 0 {
		if len(tgt.LegacyNames) > 0 {
			tgt.Satisfy.Names = tgt.LegacyNames
		} else {
			tgt.Satisfy.Names = []string{desiredKey}
		}
	}

	if tgt.Request.Provider == "" {
		tgt.Request.Provider = tgt.LegacyProvider
	}

	err = normalizeNames(tgt.Satisfy.Names)
	if err != nil {
		return nil, fmt.Errorf("invalid target: %s: %v", desiredKey, err)
	}

	if len(tgt.Request.Names) == 0 {
		tgt.Request.Names = tgt.Satisfy.Names
		tgt.Request.implicitNames = true
	}

	tgt.Request.Account, err = s.getAccountByProviderString(tgt.Request.Provider)
	if err != nil {
		return nil, err
	}

	// TODO: tgt.Priority
	return tgt, nil
}
Beispiel #6
0
func (s *fdbStore) validateAuthorizations(account *Account, c *fdb.Collection) error {
	ac := c.Collection("authorizations")

	auths, err := ac.List()
	if err != nil {
		return err
	}

	for _, auth := range auths {
		auc := ac.Collection(auth)
		err := s.validateAuthorization(account, auth, auc)
		log.Errore(err, "failed to load authorization, ignoring: ", auth)
	}

	return nil
}
Beispiel #7
0
func (s *fdbStore) validateAccount(serverName, accountName string, c *fdb.Collection) error {
	f, err := c.Open("privkey")
	if err != nil {
		return err
	}

	defer f.Close()

	b, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}

	pk, err := acmeutils.LoadPrivateKey(b)
	if err != nil {
		return err
	}

	f.Close()

	directoryURL, err := decodeAccountURLPart(serverName)
	if err != nil {
		return err
	}

	account := &Account{
		PrivateKey:     pk,
		DirectoryURL:   directoryURL,
		Authorizations: map[string]*Authorization{},
	}

	accountID := account.ID()
	actualAccountID := serverName + "/" + accountName
	if accountID != actualAccountID {
		return fmt.Errorf("account ID mismatch: %#v != %#v", accountID, actualAccountID)
	}

	s.accounts[accountID] = account

	err = s.validateAuthorizations(account, c)
	if err != nil {
		return err
	}

	return nil
}
Beispiel #8
0
func (s *fdbStore) validateAuthorizations(account *Account, c *fdb.Collection) error {
	ac := c.Collection("authorizations")

	auths, err := ac.List()
	if err != nil {
		return err
	}

	for _, auth := range auths {
		auc := ac.Collection(auth)
		err := s.validateAuthorization(account, auth, auc)
		if err != nil {
			return err
		}
	}

	return nil
}
Beispiel #9
0
// Saves a key as a file named "privkey" inside the given collection.
func (s *Store) saveKey(c *fdb.Collection, privateKey interface{}) error {
	var kb []byte
	var hdr string

	switch v := privateKey.(type) {
	case *rsa.PrivateKey:
		kb = x509.MarshalPKCS1PrivateKey(v)
		hdr = "RSA PRIVATE KEY"
	case *ecdsa.PrivateKey:
		var err error
		kb, err = x509.MarshalECPrivateKey(v)
		if err != nil {
			return err
		}
		hdr = "EC PRIVATE KEY"
	default:
		return fmt.Errorf("unsupported private key type: %T", privateKey)
	}

	f, err := c.Create("privkey")
	if err != nil {
		return err
	}
	defer f.CloseAbort()

	err = pem.Encode(f, &pem.Block{
		Type:  hdr,
		Bytes: kb,
	})
	if err != nil {
		return err
	}

	f.Close()
	return nil
}
Beispiel #10
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
}