forked from abiosoft/caddy-hmac
-
Notifications
You must be signed in to change notification settings - Fork 1
/
hmac.go
104 lines (90 loc) · 2.38 KB
/
hmac.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package hmac
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"fmt"
"hash"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
// Interface guards
var (
_ caddy.Provisioner = (*HMAC)(nil)
_ caddy.Validator = (*HMAC)(nil)
_ caddyhttp.MiddlewareHandler = (*HMAC)(nil)
_ caddyfile.Unmarshaler = (*HMAC)(nil)
)
func init() {
caddy.RegisterModule(HMAC{})
httpcaddyfile.RegisterHandlerDirective("hmac", parseCaddyfile)
}
// HMAC implements an HTTP handler that
// validates request body with hmac.
type HMAC struct {
Algorithm string `json:"algorithm,omitempty"`
Secret string `json:"secret,omitempty"`
Name string `json:"name,omitempty"`
hasher func() hash.Hash
}
// CaddyModule returns the Caddy module information.
func (HMAC) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "http.handlers.hmac",
New: func() caddy.Module { return new(HMAC) },
}
}
// Provision implements caddy.Provisioner.
func (m *HMAC) Provision(ctx caddy.Context) error {
switch hashAlgorithm(m.Algorithm) {
case algSha1:
m.hasher = sha1.New
case algSha256:
m.hasher = sha256.New
case algMd5:
m.hasher = md5.New
}
return nil
}
// Validate implements caddy.Validator.
func (m HMAC) Validate() error {
if !hashAlgorithm(m.Algorithm).valid() {
return fmt.Errorf("unsupported hash type '%s'", m.Algorithm)
}
if m.hasher == nil {
// this will never happen
return fmt.Errorf("hasher is null")
}
return nil
}
func (m HMAC) replacerKey() string {
if m.Name != "" {
return fmt.Sprintf("hmac.%s.signature", m.Name)
}
return "hmac.signature"
}
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
// hmac [<name>] <algorithm> <secret>
//
func (m *HMAC) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
args := d.RemainingArgs()
switch len(args) {
case 2:
m.Algorithm, m.Secret = args[0], args[1]
case 3:
m.Name, m.Algorithm, m.Secret = args[0], args[1], args[2]
default:
return d.Err("unexpected number of arguments")
}
}
return nil
}
// parseCaddyfile unmarshals tokens from h into a new Middleware.
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
var m HMAC
err := m.UnmarshalCaddyfile(h.Dispenser)
return m, err
}