~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/macaroon-bakery.v1/httpbakery/checkers.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package httpbakery
 
2
 
 
3
import (
 
4
        "net"
 
5
        "net/http"
 
6
 
 
7
        "gopkg.in/errgo.v1"
 
8
 
 
9
        "gopkg.in/macaroon-bakery.v1/bakery/checkers"
 
10
)
 
11
 
 
12
type httpContext struct {
 
13
        req *http.Request
 
14
}
 
15
 
 
16
// Checkers implements the standard HTTP-request checkers.
 
17
// It does not include the "declared" checker, as that
 
18
// must be added for each individual set of macaroons
 
19
// that are checked.
 
20
func Checkers(req *http.Request) checkers.Checker {
 
21
        c := httpContext{req}
 
22
        return checkers.Map{
 
23
                checkers.CondClientIPAddr: c.clientIPAddr,
 
24
                checkers.CondClientOrigin: c.clientOrigin,
 
25
        }
 
26
}
 
27
 
 
28
// clientIPAddr implements the IP client address checker
 
29
// for an HTTP request.
 
30
func (c httpContext) clientIPAddr(_, addr string) error {
 
31
        ip := net.ParseIP(addr)
 
32
        if ip == nil {
 
33
                return errgo.Newf("cannot parse IP address in caveat")
 
34
        }
 
35
        if c.req.RemoteAddr == "" {
 
36
                return errgo.Newf("client has no remote address")
 
37
        }
 
38
        reqIP, err := requestIPAddr(c.req)
 
39
        if err != nil {
 
40
                return errgo.Mask(err)
 
41
        }
 
42
        if !reqIP.Equal(ip) {
 
43
                return errgo.Newf("client IP address mismatch, got %s", reqIP)
 
44
        }
 
45
        return nil
 
46
}
 
47
 
 
48
// clientOrigin implements the Origin header checker
 
49
// for an HTTP request.
 
50
func (c httpContext) clientOrigin(_, origin string) error {
 
51
        if reqOrigin := c.req.Header.Get("Origin"); reqOrigin != origin {
 
52
                return errgo.Newf("request has invalid Origin header; got %q", reqOrigin)
 
53
        }
 
54
        return nil
 
55
}
 
56
 
 
57
// SameClientIPAddrCaveat returns a caveat that will check that
 
58
// the remote IP address is the same as that in the given HTTP request.
 
59
func SameClientIPAddrCaveat(req *http.Request) checkers.Caveat {
 
60
        if req.RemoteAddr == "" {
 
61
                return checkers.ErrorCaveatf("client has no remote IP address")
 
62
        }
 
63
        ip, err := requestIPAddr(req)
 
64
        if err != nil {
 
65
                return checkers.ErrorCaveatf("%v", err)
 
66
        }
 
67
        return checkers.ClientIPAddrCaveat(ip)
 
68
}
 
69
 
 
70
func requestIPAddr(req *http.Request) (net.IP, error) {
 
71
        reqHost, _, err := net.SplitHostPort(req.RemoteAddr)
 
72
        if err != nil {
 
73
                return nil, errgo.Newf("cannot parse host port in remote address: %v", err)
 
74
        }
 
75
        ip := net.ParseIP(reqHost)
 
76
        if ip == nil {
 
77
                return nil, errgo.Newf("invalid IP address in remote address %q", req.RemoteAddr)
 
78
        }
 
79
        return ip, nil
 
80
}