Beispiel #1
0
func (d *dischargeHandler) serveDischarge1(p httprequest.Params) (interface{}, error) {
	logger.Debugf("dischargeHandler.serveDischarge {")
	defer logger.Debugf("}")
	if p.Request.Method != "POST" {
		// TODO http.StatusMethodNotAllowed)
		return nil, badRequestErrorf("method not allowed")
	}
	p.Request.ParseForm()
	id := p.Request.Form.Get("id")
	if id == "" {
		return nil, badRequestErrorf("id attribute is empty")
	}
	checker := func(cavId, cav string) ([]checkers.Caveat, error) {
		return d.checker(p.Request, cavId, cav)
	}

	// TODO(rog) pass location into discharge
	// location := p.Request.Form.Get("location")

	var resp dischargeResponse
	m, err := d.svc.Discharge(bakery.ThirdPartyCheckerFunc(checker), id)
	if err != nil {
		return nil, errgo.NoteMask(err, "cannot discharge", errgo.Any)
	}
	resp.Macaroon = m
	return &resp, nil
}
Beispiel #2
0
// AcquireDischarge implements httpbakery.DischargeAcquirer.
func (da *dischargeAcquirer) AcquireDischarge(firstPartyLocation string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
	if cav.Location == "client:encrypt" {
		dm, _, err := bakery.Discharge(da.client.Key,
			bakery.ThirdPartyCheckerFunc(da.clientEncryptChecker), cav.Id)
		return dm, err
	}
	return da.client.AcquireDischarge(firstPartyLocation, cav)
}
Beispiel #3
0
func (d *InteractiveDischarger) wait(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	d.mu.Lock()
	discharge, ok := d.waiting[r.Form.Get("waitid")]
	d.mu.Unlock()
	if !ok {
		code, body := httpbakery.ErrorToResponse(errgo.Newf("invalid waitid %q", r.Form.Get("waitid")))
		httprequest.WriteJSON(w, code, body)
		return
	}
	defer func() {
		d.mu.Lock()
		delete(d.waiting, r.Form.Get("waitid"))
		d.mu.Unlock()
	}()
	var err error
	var cavs []checkers.Caveat
	select {
	case res := <-discharge.c:
		err = res.err
		cavs = res.cavs
	case <-time.After(5 * time.Minute):
		code, body := httpbakery.ErrorToResponse(errgo.New("timeout waiting for interaction to complete"))
		httprequest.WriteJSON(w, code, body)
		return
	}
	if err != nil {
		code, body := httpbakery.ErrorToResponse(err)
		httprequest.WriteJSON(w, code, body)
		return
	}
	m, err := d.Service.Discharge(
		bakery.ThirdPartyCheckerFunc(
			func(cavId, caveat string) ([]checkers.Caveat, error) {
				return cavs, nil
			},
		),
		discharge.cavId,
	)
	if err != nil {
		code, body := httpbakery.ErrorToResponse(err)
		httprequest.WriteJSON(w, code, body)
		return
	}
	httprequest.WriteJSON(
		w,
		http.StatusOK,
		httpbakery.WaitResponse{
			Macaroon: m,
		},
	)
}
Beispiel #4
0
func (s *ServiceSuite) TestDischargeMacaroonCannotBeUsedAsNormalMacaroon(c *gc.C) {
	locator := make(bakery.PublicKeyLocatorMap)
	firstParty := newService(c, "first", locator)
	thirdParty := newService(c, "third", locator)

	// First party mints a macaroon with a 3rd party caveat.
	m, err := firstParty.NewMacaroon("", nil, []checkers.Caveat{{
		Location:  "third",
		Condition: "true",
	}})
	c.Assert(err, gc.IsNil)

	// Acquire the discharge macaroon, but don't bind it to the original.
	d, err := thirdParty.Discharge(bakery.ThirdPartyCheckerFunc(func(_, caveat string) ([]checkers.Caveat, error) {
		return nil, nil
	}), m.Caveats()[0].Id)
	c.Assert(err, gc.IsNil)

	// Make sure it cannot be used as a normal macaroon in the third party.
	err = thirdParty.Check(macaroon.Slice{d}, checkers.New())
	c.Assert(err, gc.ErrorMatches, `verification failed: macaroon not found in storage`)
}
Beispiel #5
0
func (d *Discharger) wait(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	id, err := strconv.Atoi(r.Form.Get("waitid"))
	if err != nil {
		d.WriteJSON(w, http.StatusBadRequest, httpbakery.Error{
			Message: fmt.Sprintf("cannot read waitid: %s", err),
		})
		return
	}
	err = <-d.waiting[id].c
	if err != nil {
		d.WriteJSON(w, http.StatusForbidden, err)
		return
	}
	m, err := d.Bakery.Discharge(
		bakery.ThirdPartyCheckerFunc(
			func(cavId, caveat string) ([]checkers.Caveat, error) {
				return nil, nil
			},
		),
		d.waiting[id].cavId,
	)
	if err != nil {
		d.WriteJSON(w, http.StatusForbidden, err)
		return
	}
	d.WriteJSON(
		w,
		http.StatusOK,
		struct {
			Macaroon *macaroon.Macaroon
		}{
			Macaroon: m,
		},
	)
}
Beispiel #6
0
func (s *ServiceSuite) TestDischargeTwoNeedDeclared(c *gc.C) {
	locator := make(bakery.PublicKeyLocatorMap)
	firstParty := newService(c, "first", locator)
	thirdParty := newService(c, "third", locator)

	// firstParty mints a macaroon with two third party caveats
	// with overlapping attributes.
	m, err := firstParty.NewMacaroon("", nil, []checkers.Caveat{
		checkers.NeedDeclaredCaveat(checkers.Caveat{
			Location:  "third",
			Condition: "x",
		}, "foo", "bar"),
		checkers.NeedDeclaredCaveat(checkers.Caveat{
			Location:  "third",
			Condition: "y",
		}, "bar", "baz"),
	})
	c.Assert(err, gc.IsNil)

	// The client asks for a discharge macaroon for each third party caveat.
	// Since no declarations are added by the discharger,
	d, err := bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
		return thirdParty.Discharge(bakery.ThirdPartyCheckerFunc(func(_, caveat string) ([]checkers.Caveat, error) {
			return nil, nil
		}), cav.Id)
	})
	c.Assert(err, gc.IsNil)
	declared := checkers.InferDeclared(d)
	c.Assert(declared, gc.DeepEquals, checkers.Declared{
		"foo": "",
		"bar": "",
		"baz": "",
	})
	err = firstParty.Check(d, checkers.New(declared))
	c.Assert(err, gc.IsNil)

	// If they return conflicting values, the discharge fails.
	// The client asks for a discharge macaroon for each third party caveat.
	// Since no declarations are added by the discharger,
	d, err = bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
		return thirdParty.Discharge(bakery.ThirdPartyCheckerFunc(func(_, caveat string) ([]checkers.Caveat, error) {
			switch caveat {
			case "x":
				return []checkers.Caveat{
					checkers.DeclaredCaveat("foo", "fooval1"),
				}, nil
			case "y":
				return []checkers.Caveat{
					checkers.DeclaredCaveat("foo", "fooval2"),
					checkers.DeclaredCaveat("baz", "bazval"),
				}, nil
			}
			return nil, fmt.Errorf("not matched")
		}), cav.Id)
	})
	c.Assert(err, gc.IsNil)
	declared = checkers.InferDeclared(d)
	c.Assert(declared, gc.DeepEquals, checkers.Declared{
		"bar": "",
		"baz": "bazval",
	})
	err = firstParty.Check(d, checkers.New(declared))
	c.Assert(err, gc.ErrorMatches, `verification failed: caveat "declared foo fooval1" not satisfied: got foo=null, expected "fooval1"`)
}