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 }
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 }
// 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 }
// 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() }
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 }
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 }
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 }
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 }
// 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 }
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 }