func (as *assertsSuite) TestDecoderBrokenBodySeparation(c *C) { streamData := strings.Replace(exampleBodyAndExtraHeaders, "THE-BODY\n\n", "THE-BODY", 1) decoder := asserts.NewDecoder(bytes.NewBufferString(streamData)) _, err := decoder.Decode() c.Assert(err, ErrorMatches, "missing content/signature separator") streamData = strings.Replace(exampleBodyAndExtraHeaders, "THE-BODY\n\n", "THE-BODY\n", 1) decoder = asserts.NewDecoder(bytes.NewBufferString(streamData)) _, err = decoder.Decode() c.Assert(err, ErrorMatches, "missing content/signature separator") }
func (as *assertsSuite) TestEncoderOK(c *C) { encoded := []byte("type: test-only\n" + "authority-id: auth-id2\n" + "primary-key: xyzyz\n" + "revision: 5\n" + "header1: value1\n" + "header2: value2\n" + "body-length: 8\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" + "THE-BODY" + "\n\n" + "AXNpZw==") a0, err := asserts.Decode(encoded) c.Assert(err, IsNil) cont0, _ := a0.Signature() stream := new(bytes.Buffer) enc := asserts.NewEncoder(stream) enc.Encode(a0) c.Check(bytes.HasSuffix(stream.Bytes(), []byte{'\n'}), Equals, true) dec := asserts.NewDecoder(stream) a1, err := dec.Decode() c.Assert(err, IsNil) cont1, _ := a1.Signature() c.Check(cont1, DeepEquals, cont0) }
func (as *assertsSuite) TestEncoderDecoderHappy(c *C) { stream := new(bytes.Buffer) enc := asserts.NewEncoder(stream) asserts.EncoderAppend(enc, []byte(exampleEmptyBody2NlNl)) asserts.EncoderAppend(enc, []byte(exampleBodyAndExtraHeaders)) asserts.EncoderAppend(enc, []byte(exampleEmptyBodyAllDefaults)) decoder := asserts.NewDecoder(stream) a, err := decoder.Decode() c.Assert(err, IsNil) c.Check(a.Type(), Equals, asserts.TestOnlyType) _, ok := a.(*asserts.TestOnly) c.Check(ok, Equals, true) checkContent(c, a, exampleEmptyBody2NlNl) a, err = decoder.Decode() c.Assert(err, IsNil) checkContent(c, a, exampleBodyAndExtraHeaders) a, err = decoder.Decode() c.Assert(err, IsNil) checkContent(c, a, exampleEmptyBodyAllDefaults) a, err = decoder.Decode() c.Assert(err, Equals, io.EOF) }
func submitSerialRequest(t *state.Task, serialRequest string, client *http.Client) (*asserts.Serial, error) { st := t.State() st.Unlock() defer st.Lock() resp, err := client.Post(serialRequestURL, asserts.MediaType, bytes.NewBufferString(serialRequest)) if err != nil { return nil, retryErr(t, "cannot deliver device serial request: %v", err) } defer resp.Body.Close() switch resp.StatusCode { case 200, 201: case 202: return nil, errPoll default: return nil, retryErr(t, "cannot deliver device serial request: unexpected status %d", resp.StatusCode) } // decode body with serial assertion dec := asserts.NewDecoder(resp.Body) got, err := dec.Decode() if err != nil { // assume broken i/o return nil, retryErr(t, "cannot read response to request for a serial: %v", err) } serial, ok := got.(*asserts.Serial) if !ok { return nil, fmt.Errorf("cannot use device serial assertion of type %q", got.Type().Name) } return serial, nil }
// Assertion retrivies the assertion for the given type and primary key. func (s *Store) Assertion(assertType *asserts.AssertionType, primaryKey []string, user *auth.UserState) (asserts.Assertion, error) { u, err := s.assertionsURI.Parse(path.Join(assertType.Name, path.Join(primaryKey...))) if err != nil { return nil, err } v := url.Values{} v.Set("max-format", strconv.Itoa(assertType.MaxSupportedFormat())) u.RawQuery = v.Encode() reqOptions := &requestOptions{ Method: "GET", URL: u, Accept: asserts.MediaType, } var asrt asserts.Assertion resp, err := s.retryRequest(context.TODO(), s.client, reqOptions, user, func(ok bool, resp *http.Response) error { var e error if ok { // decode assertion dec := asserts.NewDecoder(resp.Body) asrt, e = dec.Decode() } else { contentType := resp.Header.Get("Content-Type") if contentType == jsonContentType || contentType == "application/problem+json" { var svcErr assertionSvcError dec := json.NewDecoder(resp.Body) if e = dec.Decode(&svcErr); e != nil { return fmt.Errorf("cannot decode assertion service error with HTTP status code %d: %v", resp.StatusCode, e) } if svcErr.Status == 404 { return &AssertionNotFoundError{&asserts.Ref{Type: assertType, PrimaryKey: primaryKey}} } return fmt.Errorf("assertion service error: [%s] %q", svcErr.Title, svcErr.Detail) } } return e }) if err != nil { return nil, err } if resp.StatusCode != 200 { return nil, respToError(resp, "fetch assertion") } return asrt, err }
// Known queries assertions with type assertTypeName and matching assertion headers. func (client *Client) Known(assertTypeName string, headers map[string]string) ([]asserts.Assertion, error) { path := fmt.Sprintf("/v2/assertions/%s", assertTypeName) q := url.Values{} if len(headers) > 0 { for k, v := range headers { q.Set(k, v) } } response, err := client.raw("GET", path, q, nil, nil) if err != nil { return nil, fmt.Errorf("failed to query assertions: %v", err) } defer response.Body.Close() if response.StatusCode != http.StatusOK { return nil, parseError(response) } sanityCount, err := strconv.Atoi(response.Header.Get("X-Ubuntu-Assertions-Count")) if err != nil { return nil, fmt.Errorf("invalid assertions count") } dec := asserts.NewDecoder(response.Body) asserts := []asserts.Assertion{} // TODO: make sure asserts can decode and deal with unknown types for { a, err := dec.Decode() if err == io.EOF { break } if err != nil { return nil, fmt.Errorf("failed to decode assertions: %v", err) } asserts = append(asserts, a) } if len(asserts) != sanityCount { return nil, fmt.Errorf("response did not have the expected number of assertions") } return asserts, nil }
func (as *assertsSuite) TestDecoderUnexpectedEOF(c *C) { streamData := exampleBodyAndExtraHeaders + "\n" + exampleEmptyBodyAllDefaults fstHeadEnd := strings.Index(exampleBodyAndExtraHeaders, "\n\n") sndHeadEnd := len(exampleBodyAndExtraHeaders) + 1 + strings.Index(exampleEmptyBodyAllDefaults, "\n\n") for _, brk := range []int{1, fstHeadEnd / 2, fstHeadEnd, fstHeadEnd + 1, fstHeadEnd + 2, fstHeadEnd + 6} { stream := bytes.NewBufferString(streamData[:brk]) decoder := asserts.NewDecoderStressed(stream, 16, 1024, 1024, 1024) _, err := decoder.Decode() c.Check(err, Equals, io.ErrUnexpectedEOF, Commentf("brk: %d", brk)) } for _, brk := range []int{sndHeadEnd, sndHeadEnd + 1} { stream := bytes.NewBufferString(streamData[:brk]) decoder := asserts.NewDecoder(stream) _, err := decoder.Decode() c.Assert(err, IsNil) _, err = decoder.Decode() c.Check(err, Equals, io.ErrUnexpectedEOF, Commentf("brk: %d", brk)) } }
// AddStream adds a stream of assertions to the batch. // Returns references to to the assertions effectively added. func (b *Batch) AddStream(r io.Reader) ([]*asserts.Ref, error) { start := len(b.refs) dec := asserts.NewDecoder(r) for { a, err := dec.Decode() if err == io.EOF { break } if err != nil { return nil, err } if err := b.Add(a); err != nil { return nil, err } } added := b.refs[start:] if len(added) == 0 { return nil, nil } refs := make([]*asserts.Ref, len(added)) copy(refs, added) return refs, nil }
// Assertion retrivies the assertion for the given type and primary key. func (s *Store) Assertion(assertType *asserts.AssertionType, primaryKey []string, user *auth.UserState) (asserts.Assertion, error) { url, err := s.assertionsURI.Parse(path.Join(assertType.Name, path.Join(primaryKey...))) if err != nil { return nil, err } reqOptions := &requestOptions{ Method: "GET", URL: url, Accept: asserts.MediaType, } resp, err := s.doRequest(s.client, reqOptions, user) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode != 200 { contentType := resp.Header.Get("Content-Type") if contentType == "application/json" || contentType == "application/problem+json" { var svcErr assertionSvcError dec := json.NewDecoder(resp.Body) if err := dec.Decode(&svcErr); err != nil { return nil, fmt.Errorf("cannot decode assertion service error with HTTP status code %d: %v", resp.StatusCode, err) } if svcErr.Status == 404 { return nil, &AssertionNotFoundError{&asserts.Ref{Type: assertType, PrimaryKey: primaryKey}} } return nil, fmt.Errorf("assertion service error: [%s] %q", svcErr.Title, svcErr.Detail) } return nil, respToError(resp, "fetch assertion") } // and decode assertion dec := asserts.NewDecoder(resp.Body) return dec.Decode() }
func (as *assertsSuite) TestDecodeEmptyStream(c *C) { stream := new(bytes.Buffer) decoder := asserts.NewDecoder(stream) _, err := decoder.Decode() c.Check(err, Equals, io.EOF) }