diff --git a/client/client.go b/client/client.go index 307f3eebd02fbbfc746e7a76e3130fd152e36432..5ffa395150d5a08dc2da72b50a630a0bdaca71d8 100644 --- a/client/client.go +++ b/client/client.go @@ -2,12 +2,16 @@ package client import ( "context" + "errors" "git.autistici.org/ai3/go-common/clientutil" "git.autistici.org/id/keystore" ) +// ErrNoKeys indicates that the user has no encryption keys. +var ErrNoKeys = errors.New("no keys available") + // Client for the keystore API. type Client interface { Open(context.Context, string, string, string, int) error @@ -19,9 +23,8 @@ type ksClient struct { be clientutil.Backend } -// New returns a new Client with the given Config. Use this when the -// keystore service runs on a single global instance. -func New(config *clientutil.BackendConfig) (*ksClient, error) { +// New returns a new Client with the given backend Config. +func New(config *clientutil.BackendConfig) (Client, error) { be, err := clientutil.NewBackend(config) if err != nil { return nil, err @@ -46,6 +49,12 @@ func (c *ksClient) Get(ctx context.Context, shard, username, ssoTicket string) ( } var resp keystore.GetResponse err := c.be.Call(ctx, shard, "/api/get_key", &req, &resp) + if err != nil { + return nil, err + } + if !resp.HasKey { + return nil, ErrNoKeys + } return resp.Key, err } diff --git a/protocol.go b/protocol.go index 0e65499fca4309c234b8bb852ff1b1ddce2f0f32..fc6113e36dbba6ef1d05775119dbd32e8dabec4f 100644 --- a/protocol.go +++ b/protocol.go @@ -14,7 +14,8 @@ type GetRequest struct { } type GetResponse struct { - Key []byte `json:"key"` + HasKey bool `json:"has_key"` + Key []byte `json:"key"` } type CloseRequest struct { diff --git a/server/server.go b/server/server.go index ba17efd1f119b6f3528e78a56a244752282ddc77..71a3eb225624359bbe46213d5af5a682955dc627 100644 --- a/server/server.go +++ b/server/server.go @@ -41,22 +41,26 @@ func (s *keyStoreServer) handleGet(w http.ResponseWriter, r *http.Request) { return } + var resp keystore.GetResponse key, err := s.KeyStore.Get(req.Username, req.SSOTicket) - if err != nil { - log.Printf("Get(%s) error: %v", req.Username, err) + if err == errNoKeys { + log.Printf("no keys for %s", req.Username) + } else if err != nil { // Return an appropriate error code. switch err { case errUnauthorized, errBadUser: http.Error(w, err.Error(), http.StatusForbidden) - case errNoKeys: - http.NotFound(w, r) default: + log.Printf("Get(%s) error: %v", req.Username, err) http.Error(w, err.Error(), http.StatusInternalServerError) } return + } else { + resp.HasKey = true + resp.Key = key } - serverutil.EncodeJSONResponse(w, &keystore.GetResponse{Key: key}) + serverutil.EncodeJSONResponse(w, &resp) } func (s *keyStoreServer) handleClose(w http.ResponseWriter, r *http.Request) {