|
- // Copyright 2019 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
-
- package acme
-
- import (
- "context"
- "encoding/json"
- "fmt"
- "net/http"
- )
-
- // DeactivateReg permanently disables an existing account associated with c.Key.
- // A deactivated account can no longer request certificate issuance or access
- // resources related to the account, such as orders or authorizations.
- //
- // It works only with RFC8555 compliant CAs.
- func (c *Client) DeactivateReg(ctx context.Context) error {
- url := string(c.accountKID(ctx))
- if url == "" {
- return ErrNoAccount
- }
- req := json.RawMessage(`{"status": "deactivated"}`)
- res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
- if err != nil {
- return err
- }
- res.Body.Close()
- return nil
- }
-
- // registerRFC is quivalent to c.Register but for RFC-compliant CAs.
- // It expects c.Discover to have already been called.
- // TODO: Implement externalAccountBinding.
- func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
- c.cacheMu.Lock() // guard c.kid access
- defer c.cacheMu.Unlock()
-
- req := struct {
- TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"`
- Contact []string `json:"contact,omitempty"`
- }{
- Contact: acct.Contact,
- }
- if c.dir.Terms != "" {
- req.TermsAgreed = prompt(c.dir.Terms)
- }
- res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(
- http.StatusOK, // account with this key already registered
- http.StatusCreated, // new account created
- ))
- if err != nil {
- return nil, err
- }
-
- defer res.Body.Close()
- a, err := responseAccount(res)
- if err != nil {
- return nil, err
- }
- // Cache Account URL even if we return an error to the caller.
- // It is by all means a valid and usable "kid" value for future requests.
- c.kid = keyID(a.URI)
- if res.StatusCode == http.StatusOK {
- return nil, ErrAccountAlreadyExists
- }
- return a, nil
- }
-
- // updateGegRFC is equivalent to c.UpdateReg but for RFC-compliant CAs.
- // It expects c.Discover to have already been called.
- func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) {
- url := string(c.accountKID(ctx))
- if url == "" {
- return nil, ErrNoAccount
- }
- req := struct {
- Contact []string `json:"contact,omitempty"`
- }{
- Contact: a.Contact,
- }
- res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
- if err != nil {
- return nil, err
- }
- defer res.Body.Close()
- return responseAccount(res)
- }
-
- // getGegRFC is equivalent to c.GetReg but for RFC-compliant CAs.
- // It expects c.Discover to have already been called.
- func (c *Client) getRegRFC(ctx context.Context) (*Account, error) {
- req := json.RawMessage(`{"onlyReturnExisting": true}`)
- res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK))
- if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" {
- return nil, ErrNoAccount
- }
- if err != nil {
- return nil, err
- }
-
- defer res.Body.Close()
- return responseAccount(res)
- }
-
- func responseAccount(res *http.Response) (*Account, error) {
- var v struct {
- Status string
- Contact []string
- Orders string
- }
- if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
- return nil, fmt.Errorf("acme: invalid response: %v", err)
- }
- return &Account{
- URI: res.Header.Get("Location"),
- Status: v.Status,
- Contact: v.Contact,
- OrdersURL: v.Orders,
- }, nil
- }
|